前端基础

作用域链与闭包

2019-02-15  本文已影响0人  Luigi_Lin

作用域链 Scope Chain

作用域链是一条变量对象组成的链,与执行上下文有关,用于处理标识符时进行变量查询。
函数拥有一个内部属性[[scope]],该属性由ES3规范定义,只能被JS引擎读写。[[scope]]包含一个函数被创建的作用域中对象的集合,这个集合就是作用域链。


灵魂图例.png

函数执行时,没遇到一个变量,都会在作用域链中进行查找。按顺序查AO/VO,遍历对象中的键,寻找同名标识符。若该变量对象中无同名标识符,则查找下一个VO。如果遍历完作用域链还没找到,则会抛出 * is not defined 的错误。

这就是shadow的原因,当在不同一个VO中由同名标识符时,会取前一个的值,此时后一个就被shadow了。

作用域链在代码执行时只会被with及catch改变。

  1. with
    with语句传入的对象会被插入作用域链的首位。
  2. catch
    catch语句会把捕获到的异常插入作用域链的首位。

闭包 closures

定义

有权访问另一个函数作用域中变量的函数——红宝书

能够访问自由变量(函数中既非函数参数arguments亦非局部变量的变量)的函数——MDN

当闭包被创建时,闭包的[[scope]]属性被初始化,[[scope]]包含了与执行环境作用域链相同的对象的引用。
例如:

    var x = 10;

    function test(){
      console.log(x);
    }

    (()=>{
      var x = 20;
      test();   //10
    })();

因为[[scope]]时创建执行上下文时就创建的,作用域链时这个时候确定的,是静态词法链。

Function构造器创建的函数[[scope]]只包含全局对象

例如:

    var x = 10;
    function test(){
      var y = 20;
      var test1 = Function('console.log(x)');
      var test2 = Function('console.log(y)');
      test1(); //10
      test2(); // Uncaught ReferenceError: y is not defined
    }

    test();
上一篇 下一篇

猜你喜欢

热点阅读