一、作用域的描述
JavaScript权威指南中对作用域有一句很精辟的描述:“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。”
在JavaScript中,作用域的概念和其他语言差不多,在每次调用一个函数的时候,就会进入一个函数内的作用域,当从函数返回以后,就返回调用前的作用域。
验证下刚那句权威指南中的话:
<p id="scope1" style="color:red"></p>
function echo(p, html) { p.innerHTML += html + '<br/>'; } //1、 var position = 'out'; var pscope1 = document.getElementById('scope1'); function scope1() { echo(pscope1, position); } function set1() { var position = 'in'; scope1(); } set1();
1、变量scope1定位到一个p标签,用于打印信息的显示
2、echo是一个自定义的函数,用于打印信息,形参一个是p标签,一个是需要打印的信息内容
3、最后打印出的是“out”,由于打印操作在scope1函数中,scope1中没有变量position,只能往外一层的作用域中查找,作用域关系如下图所示:
4、调用set1的作用域链大致样子如下:
二、作用域的实现
作用域的实现,并非用“堆栈”方式,而是使用列表,ECMA262中所述如下:
-
任何执行上下文时刻的作用域, 都是由作用域链(scope chain)来实现
-
在一个函数被定义的时候, 会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性
-
在一个函数对象被调用的时候,会创建一个活动对象(也就是一个对象), 然后对于每一个函数的形参,都命名为该活动对象的命名属性, 然后将这个活动对象做为此时的作用域链(scope chain)最前端, 并将这个函数对象的[[scope]]加入到scope chain中
再来看下两个实例,练练手:
function function1() { var x = 'in function1'; function inner1() { x = 'in inner1'; //没有加var,等同于在外面这个函数中做声明 } inner1(); echo(pscope1, x); } function1();
最终打印出来的结果是“in inner1”
function function2() { var x = 'in function2'; function inner2() { echo(pscope1, x); var x = 'in inner2'; //加var echo(pscope1, x); } inner2(); echo(pscope1, x); } function2();
第一个echo将打印出“undefined”,第二个echo打印出“in inner2”,第三个echo打印出“in function2”。
上面的inner2等同于下面的代码:
function inner2() { var x echo(pscope1, x); //这个时候x还未定义 x = 'in inner2'; echo(pscope1, x); }
对作用域链的理解上可能还有些问题,欢迎大家来指正。
demo下载:
http://download.csdn.net/detail/loneleaf1/7983577
参考资料:
http://www.laruence.com/2009/05/28/863.html Javascript作用域原理
http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
http://www.cnblogs.com/zxj159/archive/2013/05/30/3107923.html Javascript之匿名函数(模仿块级作用域)
http://www.web-tinker.com/article/20331.html try-catch语句的“伪块作用域”
http://msdn.microsoft.com/zh-cn/library/bzt2dkta%28v=vs.94%29.aspx 变量作用域 (JavaScript)
http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html javascript变量的作用域
http://www.nowamagic.net/librarys/veda/detail/896 深入浅出JavaScript变量作用域