深入理解JavaScript系列(1) 编写高质量JavaScript代码(3)


function updateElement() {
var el = document.getElementById("result"),
style = el.style;
// 使用el和style干点其他什么事...
}


预解析:var散布的问题(Hoisting: A Problem with Scattered vars)
JavaScript中,你可以在函数的任何位置声明多个var语句,并且它们就好像是在函数顶部声明一样发挥作用,这种行为称为 hoisting(悬置/置顶解析/预解析)。当你使用了一个变量,然后不久在函数中又重新声明的话,就可能产生逻辑错误。对于JavaScript,只 要你的变量是在同一个作用域中(同一函数),它都被当做是声明的,即使是它在var声明前使用的时候。看下面这个例子:

复制代码 代码如下:


// 反例
myname = "global"; // 全局变量
function func() {
alert(myname); // "undefined"
var myname = "local";
alert(myname); // "local"
}
func();


在这个例子中,你可能会以为第一个alert弹出的是”global”,第二个弹出”loacl”。这种期许是可以理解的,因为在第一个alert 的时候,myname未声明,此时函数肯定很自然而然地看全局变量myname,但是,实际上并不是这么工作的。第一个alert会弹 出”undefined”是因为myname被当做了函数的局部变量(尽管是之后声明的),所有的变量声明当被悬置到函数的顶部了。因此,为了避免这种混 乱,最好是预先声明你想使用的全部变量。
上面的代码片段执行的行为可能就像下面这样:

复制代码 代码如下:


myname = "global"; // global variable
function func() {
var myname; // 等同于 -> var myname = undefined;
alert(myname); // "undefined"
myname = "local";
alert(myname); // "local"}
func();


为了完整,我们再提一提执行层面的稍微复杂点的东西。代码处理分两个阶段,第一阶段是变量,函数声明,以及正常格式的参数创建,这是一个解析和进入上下文 的阶段。第二个阶段是代码执行,函数表达式和不合格的标识符(为声明的变量)被创建。但是,出于实用的目的,我们就采用了”hoisting”这个概念, 这种ECMAScript标准中并未定义,通常用来描述行为。
for循环(for Loops)
在for循环中,你可以循环取得数组或是数组类似对象的值,譬如arguments和HTMLCollection对象。通常的循环形式如下:

复制代码 代码如下:


// 次佳的循环
for (var i = 0; i < myarray.length; i++) {
// 使用myarray[i]做点什么
}


这种形式的循环的不足在于每次循环的时候数组的长度都要去获取下。这回降低你的代码,尤其当myarray不是数组,而是一个HTMLCollection对象的时候。
HTMLCollections指的是DOM方法返回的对象,例如:

复制代码 代码如下:


document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName()


还有其他一些HTMLCollections,这些是在DOM标准之前引进并且现在还在使用的。有:

复制代码 代码如下:


document.images: 页面上所有的图片元素
document.links : 所有a标签元素
document.forms : 所有表单
document.forms[0].elements : 页面上第一个表单中的所有域


集合的麻烦在于它们实时查询基本文档(HTML页面)。这意味着每次你访问任何集合的长度,你要实时查询DOM,而DOM操作一般都是比较昂贵的。
这就是为什么当你循环获取值时,缓存数组(或集合)的长度是比较好的形式,正如下面代码显示的:

复制代码 代码如下:


for (var i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]做点什么
}


这样,在这个循环过程中,你只检索了一次长度值。
在所有浏览器下,循环获取内容时缓存HTMLCollections的长度是更快的,2倍(Safari3)到190倍(IE7)之间。//zxx:此数据貌似很老,仅供参考
注意到,当你明确想要修改循环中的集合的时候(例如,添加更多的DOM元素),你可能更喜欢长度更新而不是常量。
伴随着单var形式,你可以把变量从循环中提出来,就像下面这样:

复制代码 代码如下:


function looper() {
var i = 0,
max,
myarray = [];
// ...
for (i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]做点什么
}
}


这种形式具有一致性的好处,因为你坚持了单一var形式。不足在于当重构代码的时候,复制和粘贴整个循环有点困难。例如,你从一个函数复制了一个循环到另一个函数,你不得不去确定你能够把i和max引入新的函数(如果在这里没有用的话,很有可能你要从原函数中把它们删掉)。
最后一个需要对循环进行调整的是使用下面表达式之一来替换i++。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdjdsx.html