一起聊聊JavaScript中的宣告提升

2022-11-14 18:00:13
本篇文章給大家帶來了關於的相關知識,其中主要介紹了關於宣告提升的相關內容,宣告提升是JavaScript解析器的一個特性,會對程式碼中的函數、變數宣告語句作用提取到它所在的作用域的最前面,下面一起來看一下,希望對大家有幫助。

前端(vue)入門到精通課程:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:

【相關推薦:、】

宣告提升(hosting)是 JavaScript 解析器的一個特性,它會把程式碼中的函數、變數宣告語句作用提取到它所在作用域的最前面。

函數的提升

JavaScript 是支援在函數宣告之前呼叫函數的。

say();function say() {  console.log("Hello");
}
登入後複製

解析器會掃描作用域內的程式碼,把函數宣告提取到執行程式碼的前面。所以,解析器是這樣看這段程式碼的:

function say() {  console.log("Hello");
}say();
登入後複製

除了普通函數,async function, function *, async function * 也有相同的提升效果。

var 變數宣告提升

var 關鍵字的變數宣告會被提升,但變數的賦值不會被提升。

console.log(foo); // undefinedvar foo = "bar";console.log(foo); // 'bar'
登入後複製

以上程式碼的解析結果為:

var foo;console.log(foo);
foo = "bar";console.log(foo);
登入後複製

這可能會導致一些奇怪的問題:

var x = "x in global";

(function () {  // 這裡期望讀取全域性變數
  console.log(x); // 結果為undefined. 
  /* ... */
  // 在函數內某處
  var x = "x in function";
})();
登入後複製

在過去,為了規避這種奇怪的提升,大家普遍把var 宣告寫在作用域的最前面。

var x='x';var y='y';function (){    var x;    var foo;    // ...}
登入後複製

當然,現在我們選擇不用 var,改用更合理的 letconst

letconst 變數宣告和死區

那麼,letconst 就不存在變數提升了嗎?—— 未必。

看這個例子:

const x = "x in global";

(function () {  // 這裡期望讀取全域性變數
  console.log(x); // ReferenceError: Cannot access 'x' before initialization
  /* ... */
  // 在函數內某處
  const x = "x in function";
})();
登入後複製

執行報錯,說明 const x = "x in function"; 一行影響了作用域內的上方區域程式碼。

解析器會掃描當前作用域下的 constlet 宣告,在宣告語句之前使用變數名都會觸發 ReferenceError。這樣可以避免上面提過的 var 提升問題和模糊不清的程式碼正規化。

class 關鍵字也有同樣的效果,new 一個未宣告的類也會發生 ReferenceError

new MyClass(); // ReferenceError: Cannot access 'MyClass' before initializationclass MyClass {}
登入後複製

有人認為這種情況不屬於提升,畢竟宣告和賦值都沒有提前;也有人認為這些語句在執行之前就產生了影響,其作用提升了。個人偏向後者,這是對(變數和類名)識別符號的提升。

總結

一些 JavaScript 宣告語句的效果會影響到所在的整個作用域,這種現象稱為提升。

有 3 種型別的提升:

  • function 關鍵字的宣告和賦值都提升。
  • var 關鍵字宣告提升,賦值不提升。
  • let, const, class 識別符號提升,形成死區,宣告和賦值都不提升。

【相關推薦:、】

以上就是一起聊聊JavaScript中的宣告提升的詳細內容,更多請關注TW511.COM其它相關文章!