关于闭包和匿名自执行函数的问题

有一个闭包函数的调用问题,普通调用和在闭包函数外面加一层匿名自执行函数,打印出的值不一样

普通匿名函数调用

var bib = function (){
                var a = 1;
                return function(){
                    a++;
                    console.log(a);
                }
            }
            var cc =bib();
            var dd = bib();
            cc();
            cc();
            dd();
            
            控制台打印结果:2 3 2

在闭包外层加一个匿名执行函数

var bib = (function (){
                var a = 1;
                return function(){
                    a++;
                    console.log(a);
                }
            })()
            var cc =bib;
            var dd = bib;
            cc();
            cc();
            dd();
            
            控制台打印结果:2 3 4

我理解的都是匿名自执行也是闭包,a的值都在调用函数的时候都有单独的作用域,第二种情况打印出的值应该和第一次一样,为何会有偏差呢,求解。。。

阅读 3.4k
4 个回答

匿名自执行只执行了一次,而 bib 执行了两次。造成的区别就是 cc === dd 这个表达式放在两段代码里,得到的结果是不一样的。
要达到同样的效果,第一段代码应该这样写:

// ...
    var cc =bib();
    var dd = cc ; // bib();
// ...

函数每次执行都会创建一个上下文,这就是为什么上面结果的原因,cc和dd不在同一个上下文内,所用的变量a不是同一个。

而下面的呢,你看代码也知道,cc是等于dd的,都是bib,bib是函数自调的产物,他只有一个上下文,bb和cc也都使用的这一个上下文

我理解是

var bib = (function (){
           var a = 1;
           return function(){
           a++;
           console.log(a);
          }
         })()
         var cc =bib;
         var dd = bib;
            cc();
            cc();
            dd();

就类似

var b = function (){
           var a = 1;
           return function(){
           a++;
           console.log(a);
          }
         }
var bib =  b();
var cc = bib;
var dd = bib;
cc();
cc();
dd();

说这个之前呢说一些得知道的知识点
js程序的作用域呢是词法作用域也就是静态作用域,这个作用域呢在函数定义的时候就被确定。动态作用域是在函数执行的时候才确定的。
js函数在执行之前都需要先被编译一下,然后再调js引擎进行执行。所以js的函数在执行之前都会创建一个叫执行上下文的东西,执行上下文中包含变量对象、this以及作用域链,所谓变量对象就式有一个对象,它在你这个函数执行之前收集了你在这个函数中定义的变量以及函数还有函数的参数,只不过在这个函数执行前这些变量都是undefined。然后会创建作用域链将父级的作用域链拷贝过来,随后将自身的变量对象插入到作用域链的最前面(通过这么一说应该也能想到作用域链是怎么来的了)。

回到题主的问题,先看普通匿名函数的调用

var cc =bib();
var dd = bib();

这两句其实是建立两个不同的关于bib函数的执行上下文

这也是为什么会输出2 3 2

再来看这个匿名函数自调用部分
这个匿名函数在自行调用的时候创建了一个执行上下文,did只是拿到了它内部函数的引用
这样cc=did 和 dd=did 其实都是对同一个的引用,这样不管时cc调用还是dd调用它们拿到的a都时同一个a,所以结果会是2 3 4 这一部分看起来有点单例模式那味道了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题