美文网首页
从[[scope]]说闭包

从[[scope]]说闭包

作者: 静_summer | 来源:发表于2019-08-28 16:23 被阅读0次

    闭包

    词法作用域是在定义时确定的: [[scope]]
    上下文是函数执行时的变量环境: vo + [[scope]]
    所以闭包执行的时候是通过[[scope]]来访问作用域链上的变量。

    函数的从声明到执行的过程:

    • 创建(引擎准备并填充三个变量)
      + vo:函数参数,内部变量, 函数内部声明
      + scope chain: 作用域链
      + 确定this的值并填充
    • 执行
    • 词法作用域
      代码创建时定义的静态作用域
    • 上下文
      代码运行时,this的指向

    作用域链(函数定义的时候确定):

    每个函数在定义的时候都有一个[[scopes]]属性,指向的是它的作用域链。直到函数销毁。其中closure是闭包,script指向自身变量,global指向全局变量

    [[Scopes]]: Scopes[3]
             0: Closure (foo) {y: 20}
             1: Script {bar: ƒ}
             2: Global {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, 
    
         function foo() {
             alert(x);
         }
         
         (function () {
             var x = 20;
             foo(); // 10, but not 20
         })();
         var x = 10;
         // 通过Function构造的函数,不能访问闭包变量,只能访问全局变量,[[scope]]作用域链没有closure
         function foo() {
         
         var y = 20;
         
         function barFD() { // 函数声明
             alert(x);
             alert(y);
         }
         
         var barFE = function () { // 函数表达式
             alert(x);
             alert(y);
         };
         
         var barFn = Function('alert(x); alert(y);');
         
         barFD(); // 10, 20
         barFE(); // 10, 20
         barFn(); // 10, "y" is not defined
         
         }
         
         foo();
         // 变量查找= 作用域链查找(直到global没有找到) + 原型链查找
         function foo() {
         // var x = 20;
         
         function bar() {
             alert(x);
         }
         
         bar();
         }
         
         Object.prototype.x = 10;
         
         foo(); // 20
    
     ```
    * 在代码执行阶段有两个声明能够修改作用域链:
         * with
         * catch
     ``` javascript
     // 普通的闭包的作用域链在定义的时候确定,不能修改参数的调用值
         var x = 10;
         function foo() {
             alert(x);
         }
         (function () {
             var x = 20;
             foo(); // 10, but not 20
         })();
     // 使用with之后,with绑定的对象推到作用域链的最前端,同时再进行变量赋值,能够改变参数的调用值
         var x = 10, y = 10;
    
         with ({x: 20}) {
         
         var x = 30, y = 30;
         
             alert(x); // 30
             alert(y); // 30
         }
         
         alert(x); // 10
         alert(y); // 30
     ```

    相关文章

      网友评论

          本文标题:从[[scope]]说闭包

          本文链接:https://www.haomeiwen.com/subject/nerjectx.html