2、變量提升的原理

問題:以下代碼會輸出什么宅静?

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函數(shù)showName被執(zhí)行');
}
console.log(myname)

如果要了解為什么會存在變量提升就需要先了解下變量存在哪里章蚣,提升是什么意思?
答案是:代碼在編譯階段姨夹,變量和函數(shù)會被存放到變量環(huán)境中究驴,變量的默認值會被設置為 undefined;在代碼執(zhí)行階段匀伏,JavaScript 引擎會從變量環(huán)境中去查找自定義的變量和函數(shù)。(就是存在變量環(huán)境中的意思蝴韭,繼續(xù)變量環(huán)境是啥)

首先javascript代碼的執(zhí)行過程是什么樣的呢够颠?一段 JavaScript 代碼在執(zhí)行之前需要被 JavaScript 引擎編譯,編譯完成之后榄鉴,才會進入執(zhí)行階段履磨。意思就是分兩個階段:編譯蛉抓,編譯之后生個什么東西,執(zhí)行剃诅。

3.png

編譯階段

從上圖可以看巷送,經(jīng)過編譯后,會生成兩部分內容:執(zhí)行上下文(Execution context)和可執(zhí)行代碼矛辕。

執(zhí)行上下文是 :JavaScript 執(zhí)行一段代碼時的運行環(huán)境笑跛。比如調用一個函數(shù),就會進入這個函數(shù)的執(zhí)行上下文聊品,在這個階段中飞蹂,執(zhí)行上下文會分別創(chuàng)建變量對象,建立作用域鏈翻屈,以及確定this指向陈哑。

上下文.png

以上就說明:先編譯生成執(zhí)行上下文,執(zhí)行上下文中有變量對象伸眶,變量就存在這個變量對象中

一惊窖、我們可以一行一行來分析代碼,看看編譯過程厘贼。

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函數(shù)showName被執(zhí)行');
}
console.log(myname)

第 1 行和第 2 行界酒,由于這兩行代碼不是聲明操作,所以 JavaScript 引擎不會做任何處理涂臣;
第 3 行盾计,由于這行是經(jīng)過 var 聲明的,因此 JavaScript 引擎將在環(huán)境對象中創(chuàng)建一個名為 myname 的屬性赁遗,并使用 undefined 對其初始化署辉;
第 4 行,JavaScript 引擎發(fā)現(xiàn)了一個通過 function 定義的函數(shù)岩四,所以它將函數(shù)定義存儲到堆 (HEAP)中哭尝,并在環(huán)境對象中創(chuàng)建一個 showName 的屬性,然后將該屬性值指向堆中函數(shù)的位置剖煌。如果變量與函數(shù)同名材鹦,則在這個階段,以函數(shù)值為準耕姊。

經(jīng)過編譯階段變量對象中是這樣的:

// VO 為 Variable Object的縮寫桶唐,即變量對象
VO = {
    myname : undefined,
   showName : <showName reference>  // 表示showName 的地址引用
}

執(zhí)行階段:

JavaScript 引擎開始執(zhí)行“可執(zhí)行代碼”,按照順序一行一行地執(zhí)行茉兰。

showName()
console.log(myname)
var myname = 'jack'
function showName() {
    console.log('函數(shù)showName被執(zhí)行');
}
console.log(myname)

我們可以一行一行來分析上述代碼:(執(zhí)行階段):

第 1 行尤泽,調用函數(shù)showName能夠在變量對象中找到 ,輸出 '函數(shù)showName被執(zhí)行';
第 2 行坯约,查找到myname熊咽,根據(jù)編譯階段的結果,輸出 undefined闹丐;
第 3行横殴, 將myname 賦值為jack;
第 4-6行,這就是函數(shù)聲明
第7行卿拴,查找到myname衫仑,經(jīng)過第三行的操作,輸出 'jack'巍棱;

// 執(zhí)行階段
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;
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末惑畴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子航徙,更是在濱河造成了極大的恐慌如贷,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件到踏,死亡現(xiàn)場離奇詭異杠袱,居然都是意外死亡,警方通過查閱死者的電腦和手機窝稿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門楣富,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人伴榔,你說我怎么就攤上這事纹蝴。” “怎么了踪少?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵塘安,是天一觀的道長。 經(jīng)常有香客問我援奢,道長兼犯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任集漾,我火速辦了婚禮切黔,結果婚禮上,老公的妹妹穿的比我還像新娘具篇。我一直安慰自己纬霞,他們只是感情好,可當我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布驱显。 她就那樣靜靜地躺著诗芜,像睡著了一般侨舆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绢陌,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天,我揣著相機與錄音熔恢,去河邊找鬼脐湾。 笑死,一個胖子當著我的面吹牛叙淌,可吹牛的內容都是我干的秤掌。 我是一名探鬼主播,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼鹰霍,長吁一口氣:“原來是場噩夢啊……” “哼闻鉴!你這毒婦竟也來了?” 一聲冷哼從身側響起茂洒,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤孟岛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后督勺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渠羞,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年智哀,在試婚紗的時候發(fā)現(xiàn)自己被綠了次询。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓷叫,死狀恐怖屯吊,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情摹菠,我是刑警寧澤盒卸,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站辨嗽,受9級特大地震影響世落,放射性物質發(fā)生泄漏。R本人自食惡果不足惜糟需,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一屉佳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洲押,春花似錦武花、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽专钉。三九已至,卻和暖如春累铅,著一層夾襖步出監(jiān)牢的瞬間跃须,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工娃兽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留菇民,地道東北人。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓投储,卻偏偏與公主長得像第练,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玛荞,可洞房花燭夜當晚...
    茶點故事閱讀 43,687評論 2 351

推薦閱讀更多精彩內容

  • JavaScript機制 [toc] 變量提升(Hoisting) 看代碼的執(zhí)行效果 結果 結論 在執(zhí)行過程中娇掏,若...
    劉佳闊閱讀 270評論 0 0
  • js'一段'代碼執(zhí)行前,需要先編譯勋眯,編譯后會生成兩部分內容:執(zhí)行上下文和可執(zhí)行代碼:執(zhí)行上下文:比如調用一個函數(shù)婴梧,...
    sisselxie閱讀 178評論 0 0
  • [toc] 示例代碼 僅改變了a中name的屬性值,但是最終a和b打印出來的值都被改變了凡恍。像是ab都引用了 同樣的...
    劉佳闊閱讀 339評論 0 0
  • 椫就海空間和堆空間:數(shù)據(jù)是如何存儲的? JavaScript 是什么類型的語言把這種在使用之前就需要確認其變量數(shù)據(jù)類型...
    歡欣的膜笛閱讀 306評論 0 1
  • 一嚼酝、變量提升是什么浮还? 1.1 一個變量提升的例子 執(zhí)行結果如下: 可以看到,在聲明變量前打印變量闽巩,打印出的是 un...
    笑飛閱讀 5,451評論 0 0