2、变量提升的原理

问题:以下代码会输出什么?

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函数showName被执行');
}
console.log(myname)

如果要了解为什么会存在变量提升就需要先了解下变量存在哪里,提升是什么意思?
答案是:代码在编译阶段,变量和函数会被存放到变量环境中,变量的默认值会被设置为 undefined;在代码执行阶段,JavaScript 引擎会从变量环境中去查找自定义的变量和函数。(就是存在变量环境中的意思,继续变量环境是啥)

首先javascript代码的执行过程是什么样的呢?一段 JavaScript 代码在执行之前需要被 JavaScript 引擎编译,编译完成之后,才会进入执行阶段。意思就是分两个阶段:编译,编译之后生个什么东西,执行

3.png

编译阶段

从上图可以看,经过编译后,会生成两部分内容:执行上下文(Execution context)和可执行代码

执行上下文是 :JavaScript 执行一段代码时的运行环境。比如调用一个函数,就会进入这个函数的执行上下文,在这个阶段中,执行上下文会分别创建变量对象,建立作用域链,以及确定this指向。

上下文.png

以上就说明:先编译生成执行上下文,执行上下文中有变量对象,变量就存在这个变量对象中

一、我们可以一行一行来分析代码,看看编译过程。

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函数showName被执行');
}
console.log(myname)

第 1 行和第 2 行,由于这两行代码不是声明操作,所以 JavaScript 引擎不会做任何处理;
第 3 行,由于这行是经过 var 声明的,因此 JavaScript 引擎将在环境对象中创建一个名为 myname 的属性,并使用 undefined 对其初始化;
第 4 行,JavaScript 引擎发现了一个通过 function 定义的函数,所以它将函数定义存储到堆 (HEAP)中,并在环境对象中创建一个 showName 的属性,然后将该属性值指向堆中函数的位置。如果变量与函数同名,则在这个阶段,以函数值为准。

经过编译阶段变量对象中是这样的:

// VO 为 Variable Object的缩写,即变量对象
VO = {
    myname : undefined,
   showName : <showName reference>  // 表示showName 的地址引用
}

执行阶段:

JavaScript 引擎开始执行“可执行代码”,按照顺序一行一行地执行。

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函数showName被执行');
}
console.log(myname)

我们可以一行一行来分析上述代码:(执行阶段):

第 1 行,调用函数showName能够在变量对象中找到 ,输出 '函数showName被执行';
第 2 行,查找到myname,根据编译阶段的结果,输出 undefined;
第 3行, 将myname 赋值为jack;
第 4-6行,这就是函数声明
第7行,查找到myname,经过第三行的操作,输出 'jack';

// 执行阶段
VO ->  AO   // Active Object
AO = {
    showName : <showName reference>,
    myname : 'jack',
    this: Window
}

练习:

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

推荐阅读更多精彩内容

  • JavaScript机制 [toc] 变量提升(Hoisting) 看代码的执行效果 结果 结论 在执行过程中,若...
    刘佳阔阅读 275评论 0 0
  • js'一段'代码执行前,需要先编译,编译后会生成两部分内容:执行上下文和可执行代码:执行上下文:比如调用一个函数,...
    sisselxie阅读 181评论 0 0
  • [toc] 示例代码 仅改变了a中name的属性值,但是最终a和b打印出来的值都被改变了。像是ab都引用了 同样的...
    刘佳阔阅读 341评论 0 0
  • 栈空间和堆空间:数据是如何存储的? JavaScript 是什么类型的语言把这种在使用之前就需要确认其变量数据类型...
    欢欣的膜笛阅读 309评论 0 1
  • 一、变量提升是什么? 1.1 一个变量提升的例子 执行结果如下: 可以看到,在声明变量前打印变量,打印出的是 un...
    笑飞阅读 5,456评论 0 0