zoukankan      html  css  js  c++  java
  • 谈谈我对JS作用域的理解

    Javascript语言在设计之初,就将函数设计成一种包含可执行代码逻辑的特殊对象。作为对象,函数可以像普通对象变量一样拥有可以编程读写的属性,也可以像普通变量一样传递、被引用。但是问题也来了,当函数执行时,解释器如何对代码内部的标示符进行解析呢?JS是这样做的,当函数对象被创建时,或者说函数被定义时,函数对象内部不仅包含了代码逻辑,还定义了一个内部属性[[Scope]]引用了一条作用域链(可以理解成为一个对象列表)。如果这个函数在全局环境下被定义,那这个作用域链里就只有全局作用域。

    这样说比较抽象,我们来直接分析下面的全局函数:

    var a = function(x){
        var b = 'bb';
        return b;
    };

    当这样简单一个函数进入浏览器,浏览器中的js解释器开始解释代码,因为在解释代码的时候会有标示符解析,所以在这之前,js解释器需要扫描全局,初始化全局作用域,我们编程定义的a变量也会在这个时候就被放到全局作用域里(定义提前),但是a变量仍然是undefined。当解释器自上而下解释到这段代码时,它会首先创建一个匿名函数,并将全局作用域压进函数对象的内部属性所引用的作用域链(对象列表)里。然后再把它赋值给变量a。

    如下图所示:

     

    那么当我们执行a函数时又会发生什么呢?

    a();

    首先,会创建一个内部对象,我们称这个内部对象为该函数的“执行期上下文”,一个函数的执行期上下文定义了一个函数执行的环境。函数每次执行都会创建独一无二的执行期上下文,当函数执行完毕,该执行期上下文就会被销毁。每个执行期上下文对象里都有自己的作用域链(对象列表),用来解析标示符。当执行期上下文被创建时,它的作用域链会被初始化为当前执行的函数对象里的[[Scope]]属性中所包含的对象。这些值按照它们原有的顺序被复制到执行期上下文的作用链里。这个过程一旦完成,就如图所示:

    然后,解释器创建一个称为“活动对象(activation object)”的新的内部对象,这个活动对象包含当前这个执行函数里所有的局部变量(内部var 声明的),命名参数(形参),参数合集(arguments)以及this。然后此对象会被推入执行期上下文里作用域链的前端。如下图:

     

    这时候大家是不是想到了javascript函数作用域,变量声明提前的问题呢?这个问题的根源就在这里。从上到下执行函数内部指令之前,其实解释器就已经提前获取了变量声明了^_^。(变量声明提前还有很多细节,比如声明提前但赋值不提前,函数的两种定义方式表现不一致的问题,在此就不细说了)。当函数执行上下文被创建好之后,解释器开始自上至下的解释代码了,这时每遇到一个标示符,都会遍历这个执行上下文里的作用域链:首先在最顶层的活动对象里去找,如果没找到,再找下一层,最终找到全局作用域,如果还没找到一般会报语法错误,但是当对未定义的变量执行赋值运算时,解释器会在全局作用域创建该变量并赋值。这一点很重要,编程时要小心,防止污染全局环境,或者造成内存泄露的问题。

    以上是个简单的函数,如果出现了函数嵌套又会怎么样呢?上代码:

    var a = function(x){
        var b = 'bb';
        var inner = function(){
            var c = 'cc';
        };
        return b;
    };

    在a函数里又定义了个inner函数,a函数在执行时,inner函数被定义,也就是说inner函数对象被创建,码字太辛苦直接上图了:

    从图中很明显看到,inner函数对象在创建时内部[[Scope]]属性指向的作用域链初始化为a函数执行期上下文的作用域链。当执行inner函数时也是先创建执行期上下文。执行期上下文的创建过程和执行a函数时的一样,这里就不重复了。

    如果再嵌套几层,就会这样迭代下去。。。。。

    好吧,先说到这里,本来还想说说闭包的(不过相信大家已经找到他们之间的联系了吧........^_^),不过时间有限,下次再说吧。

    本文参照了《高性能Javascript》《Javascript权威指南》。

    如有错误,不用客气直接指出,大家一起学习一起成长。。。

  • 相关阅读:
    列举常见的关系型数据库和非关系型都有那些?
    web功能测试
    经典测试用例--水杯测试
    网络协议的比较
    做性能测试准备需知
    VMware虚拟机几个常用文件夹介绍
    网络协议-----session与cookie
    H5页面测试总结
    jmeter录制手机app脚本
    python requests库学习
  • 原文地址:https://www.cnblogs.com/liubingblog/p/4332045.html
Copyright © 2011-2022 走看看