【自學程式】Hoisting 到底是什麼?前端常見面試考題

更新於 發佈於 閱讀時間約 6 分鐘

Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。

在聊 Hoisting 是什麼之前,我們要先知道 Hoisting 是由什麼議題延伸出來的討論,建議可以先閱讀下文,了解 var、const、let 的差異,再來閱讀本篇文章會比較有效率:


若你已經對 JavaScript 變數宣告的作用域有所了解,就可以繼續看下去了:


究竟什麼是 Hoisting 呢?

Hoisting 中譯為「提升」,意指 JavaScript 在執行時,會將變數、函式陳述式及 class 在執行階段(execution phases)前、創造階段(creation phases)時,先行指向記憶體位置的行為。

就程式碼面而言,被提升的變數、函式陳述式及 class 的宣告會被提升至作用域 (scope)的最上方,舉例來說:

raw-image

有沒有想過為什麼在 a 被宣告前,console.log(a) 依然取得到值(undefined)呢?

實際上,上方的程式碼從 JavaScript 運作開始到結束,經歷了以下階段:

raw-image

而變數 a 在宣告時被提升到作用域最後上方的現象就稱為 Hoisting,但要注意的是 Hoisting 只是一個 JavaScript 執行時的現象,並沒有在 ECMA ES6 中被規範、提及

基本上變數、函式、class 皆有 Hoisting 的狀況,但還是會依照宣告的方式不同而有所差異。


函式的 Hoisting 行為

首先讓我們先來看看有關函式的 hoisting 行為,這邊要注意的是,只有函式陳述式(function statement)有 Hoisting 的行為,函式表達式(function expression)是沒有的,舉例來說:

raw-image

為什麼「catName」這個函式可以在被宣告之前就可以被呼叫呢?

因為函式陳述式在 JavaScript 會被提升,所以實際上執行的順序實際上是這樣的:

raw-image


變數的 Hoisting 行為

變數的提升可以分為 var 與 const、let 兩種,第一種我們在文章的開頭介紹過了,讓我們來看看 const 與 let 的 Hoisting 行為:

raw-image

與 var 的 Hoisting 行為不同,const、let 在創造階段時,並沒有像 var 一樣擁有預設值,即便他們也有 Hoisting 的行為,但呈現方式卻不同。

當使用 const、let 宣告變數時,無法在變數宣告前取用變數,連 undefined 都不會回傳,這個現象官方稱為 TDZ(Temporal Dead Zone)。

所以這裡需要注意,ES6 之後,通常我們不會在變數宣告前取用它,一來是程式的嚴禁度,二來是 ES6 以後的新發布的本版也不建議這麼設計程式。

即便會報錯,但實際上 const 、let 還是跟 var 一樣有 Hoisting 的狀況, 只差在後者帶有 undefined 的預設值,前者沒有。


Class 的 Hoisting 行為

在 ES6 時,JavaScript 引進了類別概念(class),與函式有相同的狀況,類別陳述式(class statement)具有 Hoisting 的概念,但表達式就沒有了。

raw-image

但這邊要注意一件事:JavaScript 的類別並不會主動初始化,如果在 class 的宣告前取用該類別,還是會報錯:

raw-image

類別 Hoisting 的狀況其實也跟 const、let 很類似,明明有 Hoisting 的行為,但卻因為程式設計嚴謹度的關係,在宣告前無法取得該類別。


避免執行錯誤的解法

基本上近期的開發者,幾乎已經棄用的 var,所以完全不用考量到 var Hoising 的狀況。

那我們該如何在撰寫程式時,避免掉 Hoisting 或是 ReferenceError 的狀況呢?

其實就是「確保函式、變數、類別被宣告後再取用」,即可避免掉 Hoisting 可能造成的錯誤了。

由於文章內還有額外提到陳述式及表達式的一些相關做法,希望之後有機會可以再來跟大家分享其中差異。

希望透過今天的文章,大家可以更加了解為什麼 var 會被棄用,及程式碼排序的重要性。

關於 Hoisting 你有什麼想要跟我分享的嗎?歡迎下方留言與我分享!


希望今天的文章有幫助到正在閱讀的你,如果你喜歡我的文章的話,可以留下你的愛心或是收藏我的文章,也或者可以點選「贊助」,你的一杯咖啡絕對是我持續寫下去的動力!或是透過拍拍手,用你小小的行動支持我的創作!

我是Vivian,我們下次見。


關於我:

一名從英文系畢業的前端工程師,喜歡閱讀、寫東西及自我成長。

|Instagram: Vivian Yeh|vivian_enlife

|聯絡我:vivian.enlife@gmail.com


參考資料:Hoisting - MDN Web docs

留言
avatar-img
留言分享你的想法!
avatar-img
Vivian Yeh - 跨領域轉職的軟體工程師
447會員
103內容數
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
看更多
你可能也想看
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
什麼是提升?在 JavaScript 中,提升是指變數和函數宣告會在程式執行前被「提升」到它們所在作用域(scope)的頂部。這是 JavaScript 引擎處理程式碼時的一種行為,讓你在宣告之前就能使用某些變數或函數。
Thumbnail
什麼是提升?在 JavaScript 中,提升是指變數和函數宣告會在程式執行前被「提升」到它們所在作用域(scope)的頂部。這是 JavaScript 引擎處理程式碼時的一種行為,讓你在宣告之前就能使用某些變數或函數。
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
在進入到 React 前端框架之前,幫讀者複習有關 JavaScript 的知識。此篇著重,JavaScript 的歷史、let & const & var 差異、樣板字面值( Template Literals )、箭頭函式( Arrow Function )JS ES6 一個非常重要的前置知識。
Thumbnail
在進入到 React 前端框架之前,幫讀者複習有關 JavaScript 的知識。此篇著重,JavaScript 的歷史、let & const & var 差異、樣板字面值( Template Literals )、箭頭函式( Arrow Function )JS ES6 一個非常重要的前置知識。
Thumbnail
提升(Hoisting) 指的是在創造環境階段時就把變數準備好,這時值還沒被賦予到變數上。此類型的概念可以使用執行環境的「創造階段」與「執行階段」來理解。
Thumbnail
提升(Hoisting) 指的是在創造環境階段時就把變數準備好,這時值還沒被賦予到變數上。此類型的概念可以使用執行環境的「創造階段」與「執行階段」來理解。
Thumbnail
在JS中很重要的觀念就是hoisting,中文叫做「提升」
Thumbnail
在JS中很重要的觀念就是hoisting,中文叫做「提升」
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News