美文网首页
IIFE立即执行函数的执行机制

IIFE立即执行函数的执行机制

作者: zzglovecoding | 来源:发表于2020-07-12 23:23 被阅读0次

    问题由来

    最近看面试题的时候,看到这样一道题,请问打印什么结果

    var b = 10;
    (function b() {
      b = 20;
      console.log(b);//function b() {...}
    }())
    console.log(b);//10
    

    结果大家也看到了,function b里头的输出b的结果是本身,外层的console.log(b)的结果是10,为什么会出现这样的问题呢?
    要理解这个问题,需要先知道执行上下文,还有IIFE的执行问题。
    执行上下文,推荐javascript论代码执行上下文
    立即执行函数,推荐看一下JavaScript的IIFE(即时执行方法)
    好了,有了前面的知识准备,其实还是想不通这里是什么情况,百度了很久,查找了关于IIFE的执行过程,以及变量名和函数名重名的情况,找了半天没找到答案,然后综合了一些说法,最后推敲通了,别慌,这里我来进行解释。

    function不出现在行首,就不会当做函数的声明

    在前面我推荐那个文章里头有提到,只要不是function (){...}这样的方式,就不会被当做函数的声明,而是当做函数的表达式来处理的(这句话很重要)。

    function b() {
      b = 20;
      console.log(b);//20
    }
    b();
    console.log(b);//20
    

    先来看上述代码,为什么全部打印的都是20呢,阅读了执行上下文可知,进入这片代码的时候,function b就已经在当前执行上下文的VO对象中了,然后开始执行function b,执行的时候,由于函数内部没有b变量,于是向上,找到了VO对象里头记录的function b,于是修改了b,因此function b内部改掉了b成了20,console.log还是向上找,找到了20,funciton b执行完之后,VO对象里头的b已经是20了,所以打印结果也是20。
    可见整个修改的一个机制,就是function b由于function在行首,导致了全局的VO对象里头有function b而且一开始就有,但是如果function没有出现在行首,比如

    (function b(){...})()
    

    或者

    !function b(){...}()
    

    上面两种都是立即执行函数,前面说了,如果function不在首部,那就不是函数的声明,而是当做函数的表达式来处理的,但是我们好奇的是,如果不当做函数的声明,当做表达式,那就值得我们推敲了。

    当做函数表达式处理是怎么样的
    var b = 10;
    var b = function() {
            b = 20;
            console.log(b);//20
        }
    b();
    console.log(b);//20
    

    可以看到结果都是20,function b内部,打印的b还是20,所以很明显,b改掉的是全局的b值,已经改成了20,很明显和我们前面的出来的结果是不一样的。
    回到最开始的面试题,第二个console,打印的依然是10,说明全局的b并没有改掉,况且函数内部的b打印的结果是function b的值,所以知道,function b里头的b,一定就是function b的引用,自调用函数依然存在作用域链条,也会向上找,找到的b已经是自己,但是却改不掉,看看我们上面的例子,var b = function(){...},这里在改却改掉了,所以可以推测出结果,那就是用了const声明了b,但是存在一个问题,那就是前面已经声明了b,如果是这样一定会报错,况且最外层的b和内层的没有关系,可见const b是在一个独立的作用域内的,和外界无关,因此得出结论就是

    var b = 10;
    {
        const b = function() {
            b = 20;//这样写,会报错:// Uncaught TypeError: Assignment to constant variable.
            console.log(b);
        }
        b()
    }
    console.log(b);
    

    上面代码中,b那一句会报错,因为b是常量,他改的就是const这个b。因为我们是在模拟,所以直接这样显式的写出来,肯定就报错了,面试题当中,就是默默的失败,而不会报错(这就是他的机制吧)。
    为了验证上面的代码正确,我们可以试一下用下面的严格模式来验证

    var b = 10;
    (function b() {
      'use strict'
      b = 20;
      console.log(b)
    })() // "Uncaught TypeError: Assignment to constant variable."
    

    可见报错都是一样的,所以我们把机制已经阐述清楚了。
    根据前文中提到的,只要不是function在行首,都不会去声明函数,成为自调用函数,也就是我们这里所说的机制了,中间他会形成自己的一块作用域,这种机制就成立了,欢迎交流~

    相关文章

      网友评论

          本文标题:IIFE立即执行函数的执行机制

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