• 方法链、作用域链和原型链(二)——作用域链


    每一段javascript代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。这个作用域链是一个对象列表或链表,这组对象定义了这段代码“作用域中“的变量。

    在javascript的最顶层代码中(也就是不包含在任何函数定义内的代码),作用域链由一个全局对象组成。在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。在一个嵌套的函数体内,作用域链上至少有三个对象。

    当javascript需要查找变量x的值时,它会从链中的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为x的属性,javacript会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个对象,依次类推。如果作用链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x ,并最终抛出一个引用错误异常。

    下面是一段代码:

    <script type="text/javascript">  
        name="haha";  
        function t(){  
            var name="haha_t";  
            function s(){  
                var name="haha_s";  
                console.log(name);  
            }  
            function ss(){  
                console.log(name);  
            }  
            s();  
            ss();  
        }  
        t();  
    </script> 

    当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显

    name是"haha_s"。

    但执行ss()时,作用域链是: ss()->t()->window,所以name是”haha_t"

    对象链的创建规则:

    当定义一个函数fn时,实际上保存了一个作用域链scope_chain。当调用fn时,创建了一个新的对象obj来存储fn的局部变量,并将对象obj添加到scope_chain上,同时创建一个新的更长的表示函数调用作用域的”链“。对于嵌套函数来讲,每次调用外部函数时,作用域链都会不同,内部函数都会重新定义一遍。也就是说,在每次调用外部函数时,内部函数的代码都相同,而关联这段代码的作用域链不相同。

    另外,我们要注意以下几点:

    1、访问局部变量比全局变量速度快。

    2、因为局部变量在作用域链的顶端,在函数中将频繁使用的全局变量赋值给局部变量,可提高程序执行的效率。

    3、With语句改变作用域链,是将一个对象放入作用域链的最顶端,这样访问with语句的对象很快,但是访问局部变量就慢了一个级了。不推荐使用with语句,因为可以将对象赋值给局部变量,访问速度也很快,节省了改变作用域链的消耗。

    4、With、eval、catch子句,他们都可以改变作用域链,令到一些对访问变量进行优化的引擎没法正常优化 ,因为可以将对象赋值给局部变量,访问速度也很快,节省了改变作用域链的消耗。

  • 相关阅读:
    Cocos Creator 使用protobufjs
    Java操作MongoDB:连接&增&删&改&查
    MongoDB 权限控制
    SpringBoot 文件上传、下载、设置大小
    Java HashMap 遍历、删除、排序
    Java分割字符串
    在Windows下解决git ERROR: Permission to XXX.git denied to user
    阿里云域名+github建立网站
    Creazy Ideas 智能汽车和智能交通
    Windows上安装运行Hadoop
  • 原文地址:https://www.cnblogs.com/aaron-shu/p/4185320.html
Copyright © 2020-2023  润新知