zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

JavaScript作用域原理(一)——作用域链

2023-02-18 16:47:21 时间

一、作用域的描述

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中所述如下:

  1. 任何执行上下文时刻的作用域, 都是由作用域链(scope chain)来实现

  2. 在一个函数被定义的时候, 会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性

  3. 在一个函数对象被调用的时候,会创建一个活动对象(也就是一个对象), 然后对于每一个函数的形参,都命名为该活动对象的命名属性, 然后将这个活动对象做为此时的作用域链(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变量作用域