今日份疑惑,函数的作用域错误??

323 阅读2分钟

前言

今日学习闭包跟作用域,发现作用域(scope)跟想象中不一致,深究下原因。

闭包

红宝书上说:

在一个函数内部定义的函数会把其包含函数的活动对象添加到自己的作用域链中。

根据此现象,简单写了一段测试代码。

function test() {
      let a = 1;
      return function af() {
        console.log(a);
        let b = 2;
        let t =  4;
        return function bf() {
          console.log(b);
          let c = 3;
          return function cf() {
            console.log(c);
            let ttt = 100;
            console.log(ttt)
            return (function ts(){
              console.log('===')
            })()
          };
        };
      };
    }
    console.log(test()()()());

一共有4段执行。

按照红宝书上说的,af函数的作用域包含a;bf函数作用域包含b;cf函数作用域包含c,ts函数作用域什么都没有。(固定都有全部变量global)

但是实际结果却有些不一致。

实际截图:

微信图片_20211013234431.png

微信图片_20211013234435----2.png

微信图片_20211013234443 ---- 3.png

微信图片_20211013234449----4.png

问题:af函数打印的时候,scope 显示是跟猜想的一致的。但是bf以后就有点不一致了,看着类似于继承了af的作用域一样,下面无线套娃了。

猜想:可能是bf继承了af除global跟local以外的scope;也有可能是执行上文进栈+函数内部函数执行,栈内还没有弹出scope导致的。具体怎么验证就不知道了。

进一步猜想:前面的可能性更大点,因为scopes是静态作用域,编译时就确定了;如果是后面哪种,那么假如用变量去接受bf函数的化,栈内就需要弹出scope,下次执行的时候bf就不会存在test的closure了。

同时在af中同时定义了t变量,但是在bf函数scope上没有查到该变量,验证了红宝书说的有些道理。

总结

“在一个函数内部定义的函数会把其包含函数的活动对象添加到自己的作用域链中”可以改为"在一个函数内部定义的函数会把其包含函数的活动对象添加到自己的作用域链中,同时会继承当前函数的除global跟local以外的scope"