深入了解JavaScript中l(wèi)et/var/function的變量提升
前言
在我們的印象中,當(dāng)提到JavaScript
中的變量提升,我們想到的是“變量和函數(shù)的聲明在物理層面移動到代碼的最前面“。當(dāng)然這么說不大準(zhǔn)確,變量和函數(shù)聲明在代碼里的位置是不會變的,而是在編譯階段被放入內(nèi)存中。
可是如果我問你:let 到底有沒有提升?如果有,var / let / function三者的變量提升一致嗎?此時你的答案是什么?
接下來讓我們來探討這兩個問題,如有錯誤敬請指正。
1. let存在提升
對于let
是否存在提升這個問題,讓我們先來看以下這段代碼:
a = "global"; (function() { console.log(a); // undefined, 而不是打印出global var a; }()); { console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 1; }
對于在函數(shù)作用域下打印出undefined
,我們應(yīng)該不奇怪。但引起我注意的是在塊作用域下,拋出引用錯誤的原因是在初始化之前找不到a
。那有沒有可能a
在創(chuàng)建過程被提升?而在我發(fā)現(xiàn)ES文檔中存在[var/let hoisting]
,這讓我有理由猜測let
存在提升,只是由于暫時性死區(qū)的原因,我們不能在let a
之前使用 a
。
為了證明我的猜想,我想先從let
聲明的創(chuàng)建、初始化和賦值過程入手。
{ let a = 0; a = 1; }
上述的代碼塊中發(fā)生的過程如下:
- 找到所有用
let
聲明的變量,在環(huán)境創(chuàng)建變量; - 執(zhí)行代碼;
- 執(zhí)行
a=0
,將a
初始化為1; - 執(zhí)行
a=1
,對a
進(jìn)行賦值。
由該過程可知,如果我們在創(chuàng)建完變量后和初始化之前執(zhí)行log()
方法,控制臺將會報錯:
let a = 'global' { console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 1 }
由此一來我們就可以知道了let
在創(chuàng)建的過程被提升,而在初始化過程沒有被提升。
2. var/function的變量提升
接下來我們來看看function/var
的創(chuàng)建、初始化和賦值過程,由此看看能否探究出它們的差別。
2.1 var的變量提升
function foo() { console.log(a); // undefined var a = 0; var b = 1; } foo();
當(dāng)我們執(zhí)行foo()
時,發(fā)生以下過程(較為省略):
- 為
foo
創(chuàng)建環(huán)境; - 找到
foo
中所有被var
聲明的變量,在這個環(huán)境中創(chuàng)建變量; - 將變量初始化為 undefined;
- 執(zhí)行代碼;
- 將
a
賦值為0,b
賦值為1。
由此我們可以知道var
聲明在代碼執(zhí)行前創(chuàng)建變量并初始化,所以當(dāng)我們在var a = 0
之前執(zhí)行log(a)
方法會得到 undefined 的結(jié)果。
2.2 function的變量提升
foo('btqf'); function foo(name) { console.log("my name is" + name) // my name is btqf }
當(dāng)我們執(zhí)行foo
函數(shù)時,發(fā)生以下過程:
- 找到所有
function
聲明的變量,在環(huán)境中創(chuàng)建變量; - 將這些變量初始化并賦值;
- 執(zhí)行代碼。
由此可見,function
聲明在代碼執(zhí)行前就創(chuàng)建、初始化并賦值。
3. 總結(jié)
let
的「創(chuàng)建」過程被提升了,但是初始化沒有提升。var
的「創(chuàng)建」和「初始化」都被提升了。function
的「創(chuàng)建」「初始化」和「賦值」都被提升了。- 函數(shù)和變量相比,會被優(yōu)先提升,即函數(shù)會被提升到更靠前的位置。
值得一提的是const
與let
基本類似,唯一的區(qū)別在于const
只有創(chuàng)建和初始化,沒有賦值過程。
到此這篇關(guān)于深入了解JavaScript中l(wèi)et/var/function的變量提升的文章就介紹到這了,更多相關(guān)let/var/function變量提升內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
注意 JavaScript 中 RegExp 對象的 test 方法
注意 JavaScript 中 RegExp 對象的 test 方法...2007-01-01詳談js中數(shù)組(array)和對象(object)的區(qū)別
下面小編就為大家?guī)硪黄斦刯s中數(shù)組(array)和對象(object)的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02JavaScript使用promise處理多重復(fù)請求
處理重復(fù)請求的文章想必大家也看過了很多,大多數(shù)都是分為在response返回之前發(fā)現(xiàn)重復(fù)請求就return掉的和使用節(jié)流/防抖來間接規(guī)避用戶頻繁操作兩種版本的。本文主要介紹了JavaScript使用promise處理多重復(fù)請求,感興趣的可以了解一下2021-05-05