局部变量的优先级大于全局变量,或者说内围作用域的变量的优先级比外围的高
3#所有window对象的属性拥有全局作用域
一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等
为什么第一个alert为undefined,而第二个为true。这问题也可以延伸为——alert(b)时怎么就会找外部的b,而alert(a)时就不会往外面找?!
由上图,我们便可以推知,当前网页拥有两个a,一个b,一个test函数。如果在运行期用到除此以外的东东,如c函数或d变量啦,就会报未定义错误(用eval等非正常手段生成变量与函数的情况除外),此外,它们最多出现未赋值警告。
javascript的运行期是在为var变量与函数定义分配空间后立即执行,并且是逐行往下执行的。
函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属;
在函数add创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图所示(注意:图片只例举了全部变量中的一部分):
函数add的作用域将会在执行时用到。例如执行如下代码:
执行此函数时会创建一个称为“运行期上下文(execution context)”的内部对象,运行期上下文定义了函数执行时的环境。每个运行期上下文都有自己的作用域链,用于标识符解析,当运行期上下文被创建时,而它的作用域链初始化为当前运行函数的[[Scope]]所包含的对象。
这些值按照它们出现在函数中的顺序被复制到运行期上下文的作用域链中。它们共同组成了一个新的对象,叫“活动对象(activation object)”,该对象包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。新的作用域链如下图所示:
在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取和存储数据。该过程从作用域链头部,也就是从活动对象开始搜索,查找同名的标识符,如果找到了就使用这个标识符对应的变量,如果没找到继续搜索作用域链中的下一个对象,如果搜索完所有对象都未找到,则认为该标识符未定义。函数执行过程中,每个标识符都要经历这样的搜索过程
从作用域链的结构可以看出,在运行期上下文的作用域链中,标识符所在的位置越深,读写速度就会越慢。如上图所示,因为全局变量总是存在于运行期上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量是最慢的。所以,在编写代码的时候应尽量少使用全局变量,尽可能使用局部变量。一个好的经验法则是:如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。例如下面的代码:
这个函数引用了两次全局变量document,查找该变量必须遍历整个作用域链,直到最后在全局对象中才能找到。这段代码可以重写如下:
通过这图也教育我们,一定要用局部变量啊,要不,一层层往上爬,效率是多么低啊。另外,这图也告诉我们,window是一个多么高级的存在啊,Object都比它低一等,更别提什么继承问题啦!(在FF与IE中)
该篇总结的形成得益于众多优质博客作者的知识分享,现将该篇文章涉及到的资料地址罗列如下:
参考资料:
http://www.ibm.com/developerworks/cn/web/1103_qinjian_javascriptscope/
http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html