JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解
正文
對(duì)一些計(jì)算機(jī)語言來說,程序被執(zhí)行時(shí),對(duì)命令的翻譯通常是自上而下逐行執(zhí)行的,這通常被稱為代碼解釋;
對(duì)另外一些語言來說,這種翻譯是預(yù)先進(jìn)行的,被稱為代碼編譯,這樣在程序執(zhí)行的時(shí)候,運(yùn)行的就是已經(jīng)編譯好的、可執(zhí)行的計(jì)算機(jī)指令。
JavaScript通常被認(rèn)為是解釋型的,因?yàn)槊看螆?zhí)行js源碼時(shí)都需要進(jìn)行處理。但這么說也不是完全準(zhǔn)確的,我們需要知道,JavaScript引擎實(shí)際上是動(dòng)態(tài)編譯程序,然后立即執(zhí)行編譯后的代碼。而JavaScript中的變量聲明和函數(shù)提升的直接原因就是編譯階段編譯器所做的事。
在提升過程中,雖然聲明似乎在程序中被提升了,但實(shí)際發(fā)生的事情是,函數(shù)和變量聲明在編譯階段被添加到內(nèi)存中。
一.變量提升
就變量和常量而言,關(guān)鍵字 var 被提升,let 和 const 不允許提升。
a = 5; console.log(a); var a; // 5
在上面的示例中,在聲明變量 a 之前使用它。程序運(yùn)行并顯示輸出 5。該程序的作用如下:
var a; a = 5; console.log(a); // 5
然而在 JavaScript 中,初始化不會(huì)被提升。
console.log(a);//undefined var a = 5;
上述程序的作用如下:
var a; console.log(a); a = 5;
在編譯階段,只有聲明被移動(dòng)到內(nèi)存中。因此,變量 a 的值是 undefined,因?yàn)?a 是在未初始化的情況下打印的。注意:當(dāng)變量在函數(shù)內(nèi)部使用時(shí),變量?jī)H被提升到函數(shù)的頂部。
var a = 4;
function greet() {
b = 'hello';
console.log(b);
var b;
}
greet(); // hello
console.log(b);//Uncaught ReferenceError: b is not defined
如果變量與 let (const)關(guān)鍵字一起使用,則不會(huì)提升該變量。
a = 5; console.log(a);// error let a;
換一種角度說,變量與let(const)關(guān)鍵字一起使用,變量被提升到暫時(shí)性死區(qū)(TDZ)中,直到程序執(zhí)行到該變量的let(const)聲明語句的時(shí)候才從TDZ中被釋放。
二.函數(shù)提升
由于函數(shù)聲明和變量聲明都會(huì)被提升,函數(shù)會(huì)先被提升,然后才是變量,并且后面的函數(shù)聲明會(huì)覆蓋前面的。
代碼示例:
foo();
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
};
最終結(jié)果會(huì)輸出1。因?yàn)楹瘮?shù)聲明會(huì)被提升,而函數(shù)表達(dá)式不會(huì)被提升。這段代碼可以理解成:
function foo(){
console.log(1);
}
foo();
foo = function(){
console.log(2);
};
三.判斷順序
執(zhí)行函數(shù)中的第一行代碼時(shí),如何判斷該函數(shù)的詞法作用域中存在哪些變量呢?該變量代表的是什么呢?判斷步驟如下:
- 將參數(shù)列表中的參數(shù)作為變量標(biāo)識(shí)符存儲(chǔ)在作用域中,值為undefined;
- 將傳入的實(shí)參對(duì)應(yīng)給相應(yīng)的參數(shù)列表中的標(biāo)識(shí)符賦值;
- 函數(shù)提升;若作用域中有與函數(shù)名同名的標(biāo)識(shí)符,則該函數(shù)取代該標(biāo)識(shí)符的值;
- var提升;若作用域中有同名的標(biāo)識(shí)符,則不做任何改變,否則在作用域中添加該標(biāo)識(shí)符,且值為undefined;
- 執(zhí)行第一行代碼。
四.其他“提升”
1.作為import結(jié)果的聲明是“提升的”;
foo();
import { foo } from "foo";
上面這段代碼中,foo()是可以運(yùn)行的,不只是因?yàn)閕mport...語句的靜態(tài)決議在編譯過程中確定了foo值是什么,也因?yàn)樗?ldquo;提升”了在模塊作用域頂層的聲明,使它在模塊所用位置可用。
以上就是JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于JS 變量提升函數(shù)提升的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù)的詳解
這篇文章主要介紹了微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
JS 判斷某變量是否為某數(shù)組中的一個(gè)值的3種方法(總結(jié))
JS設(shè)計(jì)模式之?dāng)?shù)據(jù)訪問對(duì)象模式的實(shí)例講解
JavaScript中的立即執(zhí)行函數(shù)表達(dá)式介紹
js實(shí)現(xiàn)前端圖片上傳即時(shí)預(yù)覽功能

