相对于C/C++来说,ECMAScript里的for循环并不能创建一个局部的上下文。
for (var k in {a: 1, b: 2}) { alert(k); }
alert(k); // 尽管循环已经结束但变量k依然在当前作用域
任何时候,变量只能通过使用var关键字才能声明。
上面的赋值语句:
a = 10;
这仅仅是给全局对象创建了一个新属性(但它不是变量)。“不是变量”并不是说它不能被改变,而是指它不符合ECMAScript规范中的变量概念,所以它“不是变量”(它之所以能成为全局对象的属性,完全是因为javascript中存在一个global对象,这样的操作不是声明一个变量而是给global对象增加一个a属性。
下面看一个简单的例题来说明问题
if (!("a" in window)) { var a = 1; } alert(a);
首先,所有的全局变量都是window的属性,语句 var a = 1;等价于window.a = 1;
你可以用如下方式来检测全局变量是否声明
"变量名称" in window
第二,所有的变量声明都在范围作用域的顶部,看一下相似的例子:
alert("a" in window); var a;
此时,尽管声明是在alert之后,alert弹出的依然是true,这是因为JavaScript引擎首先会扫墓所有的变量声明,然后将这些变量声明移动到顶部,最终的代码效果是这样的:
var a; alert("a" in window);
第三,你需要理解该题目的意思是,变量声明被提前了,但变量赋值没有,因为这行代码包括了变量声明和变量赋值。
你可以将语句拆分为如下代码:
var a; //声明 a = 1; //初始化赋值
所以总结起来就是当变量声明和赋值在一起用的时候,JavaScript引擎会自动将它分为两部以便将变量声明提前,不将赋值的步骤提前是因为他有可能影响代码执行出不可预期的结果。
题目中的代码相当于:
var a; if (!("a" in window)) { a = 1; } alert(a);
根据上述例题的分析,声明变量时如果是声明的局部变量前面一定要加var,如果声明的是全局变量可以不加var(最好限制全局变量的个数,尽量使用局部变量)
下面讲述一个使用var的几个特性
使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误。
如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色。
如果重复使用的一个声明没有一个初始值,那么它不会对原来存在的变量有任何的影响。
没有var声明的变量,是作为全局变量存在的;有var声明的变量,属于局部变量,尤其是在函数内部。并且,经过测试,带var声明比不带var速度要快。函数内尽量多设局部变量,这样即安全又快速,变量操作也更加合理,不会因为函数内胡乱操作全局变量而导致逻辑错误。
声明对象时最好使用对象自面量的方式,这样的速度相对new的方式要快很多。
变量名是自己取的,为了照顾语义和规范,变量名可能稍长,但是注意了,变量名的长度也会影响代码的执行速度。长的变量名声明的执行速度没有短的快。