看一个有趣的例子,它显示了关于局部和全局作用域的一个重要问题:
var a =123; function f() { console.log(a); var a = 1; console.log(a); } f();
您可能会想当然的认为console.log()第一次显示123(也就是全局变量a的值),第二次显示1(即局部变量a)。但事实并非完全如此,查看firebug输出结果,如下:
> undefined > 1
这是因为函数域始终优于全局域,所以局部变量a会覆盖掉所有与它同名的全局变量,尽管在console.log()第一次被调用时,a还没有被正式定义(即该值为undefined),但该变量本身已经存在于本地空间了。这种特殊现象叫做提升(hoisting)。
也就是说,当Javascript执行过程进入新的函数时,这个函数内部声明的所有变量都会被移动(或者说提升)到函数最开始的地方。这个概念很重要,必须牢记。另外需要注意的是,被提升的只有变量声明,这意味着,只有函数体内声明的这些变量在该函数执行开始时就存在,而与之相关的赋值操作并不会被提升,它还在原来的位置上。上述例子可以被等价的写为:
var a =123; function f() { var a; // some as: var a= undefined; console.log(a); // undefiend; var a = 1; console.log(a); // 1 }
再看一个有趣的例子:
console.log('global1:' + window.a); function hehe() { console.log('func area1:' + window.a); console.log('func area2:' + a); } hehe(); console.log('global2:' + window.a);
您可能认为输出结果是这样的:
> global1: undefined > func area1: undefined > func area2: undefiend > global2: undefined
通过查看firebug控制台,实际结果是这样的:
> global1:undefined > func area1:undefined > ReferenceError: a is not defined
在输出func area1的时候出错了。为什么func area1 和func area2不同呢,a不应该是全局变量吗?如果因为未定义而出错,那window.a为啥不出错?
原来,在javascript里,如果访问的对象的属性不存在,代码就会返回undefiend,window.a属于不存在的属性,所以返回undefined,而a属于不存在的变量,故出错,二者性质不通,把window.a改成其他对象效果是一样的:
var o = {}; console.log(o.v);