JavaScript中的聲明提升實(shí)例詳解
函數(shù)的提升
聲明提升(hosting)是 JavaScript 解析器的一個(gè)特性,它會(huì)把代碼中的函數(shù)、變量聲明語(yǔ)句作用提取到它所在作用域的最前面。
JavaScript 是支持在函數(shù)聲明之前調(diào)用函數(shù)的。
say(); function say() { console.log("Hello"); }
解析器會(huì)掃描作用域內(nèi)的代碼,把函數(shù)聲明提取到執(zhí)行代碼的前面。所以,解析器是這樣看這段代碼的:
function say() { console.log("Hello"); } say();
除了普通函數(shù),async function
, function *
, async function *
也有相同的提升效果。
var 變量聲明提升
var
關(guān)鍵字的變量聲明會(huì)被提升,但變量的賦值不會(huì)被提升。
console.log(foo); // undefined var foo = "bar"; console.log(foo); // 'bar'
以上代碼的解析結(jié)果為:
var foo; console.log(foo); foo = "bar"; console.log(foo);
這可能會(huì)導(dǎo)致一些奇怪的問題:
var x = "x in global"; (function () { // 這里期望讀取全局變量 console.log(x); // 結(jié)果為undefined. ?? /* ... */ // 在函數(shù)內(nèi)某處 var x = "x in function"; })();
在過去,為了規(guī)避這種奇怪的提升,大家普遍把var
聲明寫在作用域的最前面。
var x='x'; var y='y'; function (){ var x; var foo; // ... }
當(dāng)然,現(xiàn)在我們選擇不用 var
,改用更合理的 let
和 const
。
let 和 const 變量聲明和死區(qū)
那么,let
和 const
就不存在變量提升了嗎?—— 未必。
看這個(gè)例子:
const x = "x in global"; (function () { // 這里期望讀取全局變量 console.log(x); // ReferenceError: Cannot access 'x' before initialization /* ... */ // 在函數(shù)內(nèi)某處 const x = "x in function"; })();
執(zhí)行報(bào)錯(cuò),說明 const x = "x in function";
一行影響了作用域內(nèi)的上方區(qū)域代碼。
解析器會(huì)掃描當(dāng)前作用域下的 const
和 let
聲明,在聲明語(yǔ)句之前使用變量名都會(huì)觸發(fā) ReferenceError
。這樣可以避免上面提過的 var
提升問題和模糊不清的代碼范式。
class
關(guān)鍵字也有同樣的效果,new
一個(gè)未聲明的類也會(huì)發(fā)生 ReferenceError
。
new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization class MyClass {}
有人認(rèn)為這種情況不屬于提升,畢竟聲明和賦值都沒有提前;也有人認(rèn)為這些語(yǔ)句在執(zhí)行之前就產(chǎn)生了影響,其作用提升了。個(gè)人偏向后者,這是對(duì)(變量和類名)標(biāo)識(shí)符的提升。
總結(jié)
一些 JavaScript 聲明語(yǔ)句的效果會(huì)影響到所在的整個(gè)作用域,這種現(xiàn)象稱為提升。
有 3 種類型的提升:
function
關(guān)鍵字的聲明和賦值都提升。var
關(guān)鍵字聲明提升,賦值不提升。let
,const
,class
標(biāo)識(shí)符提升,形成死區(qū),聲明和賦值都不提升。
以上就是JavaScript中的聲明提升實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 聲明提升的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
es6數(shù)組之?dāng)U展運(yùn)算符操作實(shí)例分析
這篇文章主要介紹了es6數(shù)組之?dāng)U展運(yùn)算符操作,結(jié)合實(shí)例形式總結(jié)分析es6數(shù)組擴(kuò)展運(yùn)算符具體原理、實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04JS中使用TextDecoder解碼二進(jìn)制數(shù)據(jù)(數(shù)據(jù)流的逐步解碼)
JS中使用TextDecoder將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為可讀文本字符串,首先,創(chuàng)建TextDecoder對(duì)象,使用decode()方法,解碼為字符串,,{stream:true}選項(xiàng)允許處理流式數(shù)據(jù),適用于大型數(shù)據(jù)流的逐步解碼,TextDecoder廣泛應(yīng)用于WebSocket通信、文件讀取、網(wǎng)絡(luò)響應(yīng)等場(chǎng)景2024-10-10js獲取當(dāng)前日期時(shí)間及其它日期操作匯總
這篇文章主要介紹了js獲取當(dāng)前日期時(shí)間及其它日期操作匯總,感興趣的小伙伴們可以參考一下2016-03-03在JavaScript中驗(yàn)證URL的新方法(2023版)
在JavaScript領(lǐng)域,URL 驗(yàn)證方面有了新消息!多年來,人們一直在討論JavaScript沒有一種簡(jiǎn)便的方法來驗(yàn)證 URL,現(xiàn)在有了一種新方法URL.canParse(),需要的朋友可以參考下2023-09-09js getElementsByTagName的簡(jiǎn)寫方式
用最少的代碼,做最多的事情. getElementsByTagName的簡(jiǎn)寫方法.2010-06-06