JavaScript面試考題:Hoisting是什麼?

閱讀時間約 5 分鐘
在JS中很重要的觀念就是hoisting,中文叫做「提升」。先來看看以下程式碼:
var a ='Hello World!'

function b(){
console.log('Called b!')
}

b();
console.log(a)
可想而知會印出:
//Called b!
//Hello World!
那如果將b()和console.log(a)放到程式碼前面呢?
b();
console.log(a)

var a ='Hello World!'

function b(){
console.log('Called b!')
}
JS都是逐行逐行執行的,照理來說函式b沒有被宣告就被執行,應該會報錯,但事實不然,b()跟console.log(a)都不會報錯,b()會執行程式,a則會報個undefined:
//Called b!
//undefined
這是因為hoisting

網路解釋的hoisting

比較常看到的解釋是說hoisting會在執行時,把變數和函式提升到程式碼的頂部:
function b(){
console.log('Called b!')
}
var a;

b();
console.log(a)

var a ='Hello World!'
而變數又比較不一樣,它只會提升var a ,不會提升後面的值’Hello World!’,於是JavaScript 全攻略:克服 JS 的奇怪部分的老師Anthony Alicea提出不同的觀念想法,我覺得也蠻好記的。

Anthony Alicea的hoisting

首先我們必須先明白,電腦並不是直接執行我們寫的JS code,而是透過一個轉譯器「syntax parser 語法解析器」來檢查我們寫的程式碼,並轉譯成電腦懂的語言讓電腦去執行。
轉譯給電腦後,JS會製造出一個execution context執行環境,被執行的程式碼會被包起來裝在執行環境中,而執行環境分為兩個階段:
  1. Creation Phase 創造階段
  2. Execution Phase 執行階段
在Creation Phase時,JS會自動幫變數和函式製造出記憶體空間,所以在執行前,JS已經知道有這個變數a還有函式b()。
但在執行前,JS只知道有這個變數a,還不知道a的值是多少,設值是執行後才會知道的,所以JS會給undefined這個預設值。

Creation Phase 創造階段

JS:哦哦我知道有a這個變數,也知道b這個函式!b要執行的是console.log(‘Called b!’),但我還不知道a會是多少,而a的預設值是undefined。
b();
console.log(a)

var a ='Hello World!'

function b(){
console.log('Called b!')
}

// Called b!
// undefined

Execution Phase 執行階段

JS:我知道a是多少了!!是Hello World!
b();
console.log(a)

var a ='Hello World!'

function b(){
console.log('Called b!')
}

console.log(a)

// Called b!
// undefined
// Hello World!
沒宣告就執行→還是會報錯
b();
console.log(a)

function b(){
console.log('Called b!')
}

//Called b!
//Uncaught ReferenceError: a is not defined
因為根本沒有宣告a,JS的記憶體中沒有a這個變數。

undefined跟ReferenceError: a is not defined 有何不同?

undefined:代表這個值還沒被設定,而undefined是JS中特殊的值(value)
var a;
console.log(a)

if(a === undefined){
console.log('a is undefined')
}else{
console.log('a is defined')
}

// undefined
// a is undefined
a === undefined
如果沒有var a;
console.log(a)

if(a === undefined){
console.log('a is undefined')
}else{
console.log('a is defined')
}

// Uncaught ReferenceError: a is not defined
因為JS在記憶體中找不到a,所以就會報錯。
undefined是JS中特殊的value。
老師建議沒事不要把執行放在宣告前,很容易搞錯,還是按照順序就好嚕;
var a ='Hello World!'

function b(){
console.log('Called b!')
}

console.log(a)
b()

// Hello World!
// Called b!
至於要用網路上廣泛的解釋方式還是老師的解釋,我是覺得沒差,反正知道結果就好了。
2會員
2內容數
前端筆記希望不要再鬼打牆
留言0
查看全部
發表第一個留言支持創作者!
溫蒂蒂蒂的沙龍 的其他內容
在搞清楚事件委託前必須先了解什麼是事件傳遞機制(Event Propagation),也就是捕獲(capture)跟冒泡(bubble),聽起來好像很難但是我昨天看完彭彭的直播課程(17:00開始)後就懂了!我寫成文章幫助記憶,也希望能幫助到大家,然後希望我面試會被考到。
在搞清楚事件委託前必須先了解什麼是事件傳遞機制(Event Propagation),也就是捕獲(capture)跟冒泡(bubble),聽起來好像很難但是我昨天看完彭彭的直播課程(17:00開始)後就懂了!我寫成文章幫助記憶,也希望能幫助到大家,然後希望我面試會被考到。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
套件(Package)是將程式或程式庫進行組織、分發和共享的一種方式。在軟體開發中,套件通常包含了相關的程式碼、資源文件和元數據,並提供了統一的名稱空間和版本管理。
Thumbnail
當你在開發程式時,難免會遇到各種錯誤和異常情況。這些錯誤可能是因為代碼中的錯誤、外部資源無法訪問或其他不可預期的狀況。為了提高程式的可靠性、穩定性和可維護性,我們使用「例外處理」來處理這些異常情況。
<template> <div id="charge"> <el-card class="box-card"> <ul class="msg-box"> <li> <h4>充值</h4> </li> <li>
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Thumbnail
執行以上程式碼,然後看到了這個結果: 為什麼「延遲0秒」的函式寫在上方,但在console印出的結果,它還是被排在第二順位? 利用AC教材提供的youtube演講連結一窺究竟: 演講提供了更多JS的細節概念,身為JS新手的我還在消化,但若針對教案提出的問題來回答,加上利用google大神查到MDN的
Java script 中有其中兩種宣告分別是 var 跟 let var 結果: let 結果: ** let 是一種區塊的變數宣告像是 if else while for 即跳出區塊時就無法取得資料
Thumbnail
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
Thumbnail
上篇介紹的promise chain的寫法,是已經比原本好維護了沒錯,但是可讀性似乎還是有點不足,其實還可以改成用async/await的寫法,如下: E 其中,async是非同步的意思,等於是把getData()這個function定義為非同步,因此從console可以看到,test是最先被pri
Thumbnail
輸入畫面 為什麼要做驗證? 因為作為設計者,永遠不該預設使用者會乖乖照設計者的意思輸入。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
套件(Package)是將程式或程式庫進行組織、分發和共享的一種方式。在軟體開發中,套件通常包含了相關的程式碼、資源文件和元數據,並提供了統一的名稱空間和版本管理。
Thumbnail
當你在開發程式時,難免會遇到各種錯誤和異常情況。這些錯誤可能是因為代碼中的錯誤、外部資源無法訪問或其他不可預期的狀況。為了提高程式的可靠性、穩定性和可維護性,我們使用「例外處理」來處理這些異常情況。
<template> <div id="charge"> <el-card class="box-card"> <ul class="msg-box"> <li> <h4>充值</h4> </li> <li>
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Thumbnail
執行以上程式碼,然後看到了這個結果: 為什麼「延遲0秒」的函式寫在上方,但在console印出的結果,它還是被排在第二順位? 利用AC教材提供的youtube演講連結一窺究竟: 演講提供了更多JS的細節概念,身為JS新手的我還在消化,但若針對教案提出的問題來回答,加上利用google大神查到MDN的
Java script 中有其中兩種宣告分別是 var 跟 let var 結果: let 結果: ** let 是一種區塊的變數宣告像是 if else while for 即跳出區塊時就無法取得資料
Thumbnail
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
Thumbnail
上篇介紹的promise chain的寫法,是已經比原本好維護了沒錯,但是可讀性似乎還是有點不足,其實還可以改成用async/await的寫法,如下: E 其中,async是非同步的意思,等於是把getData()這個function定義為非同步,因此從console可以看到,test是最先被pri
Thumbnail
輸入畫面 為什麼要做驗證? 因為作為設計者,永遠不該預設使用者會乖乖照設計者的意思輸入。