面試|變量提升與函數提升,挑戰下這幾個例子?

語言: CN / TW / HK

theme: github highlight: a11y-dark


本文已參與「新人創作禮」活動,一起開啟掘金創作之路。

雙11期|變量提升與函數提升

tips:每個技術點都值得優學優寫:11期

好文推薦:

約2萬字-Vue源碼解讀彙總篇(續更)

前端要會打組合拳,覆盤30+技術點打出的功能

通常我們認為變量需要先聲明再使用,才不會報錯,但在 JavaScript 種, 先使用一個變量後面再使用 var 聲名賦值,不會被拋出異常,而是該值為 undefined。

JavaScript 變量感覺上是被“提升”或移到了函數或語句的最前面,這種現象被人稱為“變量提升”。

對於 JavaScript 中的函數來説,也有“函數提升”的現象。

變量提升

“變量提升”的存在,使得變量像是聲明提前,聲明語句被移動到環境的頂部似得。 但“變量提升”(聲明提前),在使用不同的關鍵字聲明的時候,表現又不盡一致。

例如下面的例子。

```js // 先使用變量 x,再通過 var 聲明並初始化賦值3給它。此時提前使用變量 x 不會拋出異常,x 的值為 undefined。 console.log(x === undefined) // true console.log(x) // undefined var x = 3

// 變量依然被“提升”了,但不會被賦予初始值,提前使用變量 y,將拋出引用錯誤(ReferenceError)。 console.log(y) let y = 2

// const 和 let 的情況一樣,也會拋出引用錯誤(ReferenceError) console.log(z) const z = 1 ```

使用 var 聲明的變量,存在變量提升現象,但不會拋出異常,默認值會被設置為 undefined。

在 ECMAScript 6 中,let 和 const 同樣會被提升變量到代碼塊的頂部但是不會被賦予初始值。 在變量聲明之前引用這個變量, 將拋出引用錯誤(ReferenceError)。 這個變量將從代碼塊一開始的時候就處在一個“暫時性死區”,直到這個變量被聲明為止。

下面是一張使用 let 聲明的變量被提前使用的報錯截圖。

image.png

函數提升

JavaScript 中,函數 function 也存在“聲明提前”的現象。 不同的是對於函數來説,只有函數聲明會被提升到頂部,而函數表達式不會被提升。

例如下面的例子。

```js / 函數聲明:函數提升了,成功執行了打印語句,沒有拋出異常 / test(); // "測試函數聲明提升"

function test() { console.log("測試函數聲明提升"); }

/ 函數表達式:沒有被提升,拋出了 typeError: testExpression is not a function / testExpression(); // 類型錯誤:baz 不是一個函數 var testExpression = function() { console.log("測試函數表達式提升"); }; ```

這是一張前面的例子,關於函數提升和函數表達式不提升的測試截圖:

image.png

幾個有趣的例子

例子一:執行下面的代碼,控制枱輸出結果是什麼?

```js var test = function () { console.log(1) }

function test () { console.log(2) }

test() ```

例子二:執行下面的代碼,控制枱輸出結果是什麼?

```js function test () { console.log(2) }

var test = function () { console.log(1) }

test() ```

例子三:執行下面的代碼,控制枱輸出結果是什麼?

```js var test = "1"

function test () { console.log(2) }

test() ```

例子四:執行下面的代碼,控制枱輸出結果是什麼?

```js let test = function () { console.log(2) }

function test () { console.log(2) }

test() ```

上面幾個例子執行結果是啥,歡迎評論區分享你的答案。 關於錯誤類型,可以參考這篇 基本對象Error及8種錯誤類型