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

问题由来

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

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在行首,都不会去声明函数,成为自调用函数,也就是我们这里所说的机制了,中间他会形成自己的一块作用域,这种机制就成立了,欢迎交流~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354