顯示廣告
隱藏 ✕
※ 本文為 terievv 轉寄自 ptt.cc 更新時間: 2017-02-26 06:57:25
看板 Ajax
作者 eight0 (人類)
標題 Re: [問題] Hoisting 問題
時間 Sun Feb 19 23:24:23 2017


我覺得原 PO 的問題可能不是 hoisting,而是不知道 test = ... 會把 function test
覆蓋掉。不過這篇還是講 hoisting。

Hoisting 這個「行為」是被人「觀察」出來的。以 C 為例子︰

        #include <stdio.h>
        int a = 1;
        int main() {
                printf("%d\n", a);
                int a = 2;
                printf("%d\n", a);
        }

得到的結果會是

        1
        2

但在 JavaScript 中

        var a = 1;
        function main() {
                console.log(a);
                var a = 2;
                console.log(a);
        }
        main();

得到的結果是

        undefined
        2

人們就給出一套解釋︰「以 var 定義的變數,會被提到 function scope[1] 的最上面,
而且初始值是 undefined。並且會等到原本的位置(a = 2)才會賦值」,稱為
「Hoisting」。(其實這個說法是錯的,在定義 var 時並所謂的「初始值」並不一定是
 undefined,可能該變數本來就在 scope 內,或是被 function arguments 賦值)

[1]: 關於 scope: https://is.gd/tcHqDy
block - JavaScript | MDN
[圖]
A block statement (or compound statement in other languages) is used to group zero or more statements. The block is delimited by a pair of curly brack ...

 

事實上 JS 做的事情是︰在進入一個新的 scope 的時候,會把 var, function,
const, let 的變數收集起來,並且把變數名稱註冊到目前的 scope 中,接著才開始執行
接下來的程式碼。


它們之前的差別︰

var 是丟到 function scope,並且可以重覆定義,在未賦值前存取會得到 undefined。

function 也是丟到 function scope,可以重覆定義。若定義是放在 scope 的最外層

(定義位於 function scope 底下,而且不在任何 block scope 內),則會提前賦值,
所以你可以在 function 定義前就使用這個變數。否則就和 var 相同,在未賦值前存
取會得到 undefined。

const 和 let 是丟到 block scope,不能重覆定義,在還未賦值前存取會
ReferenceError。

const 還有一個限制是不能重覆賦值。


至於 const, let 也有 hoisting 現象,解釋為「將定義提升到 block scope 的最上
方,但若提前存取會丟出 ReferenceError」,並使用 temporal dead zone 的概念。
要解釋這個的話又和 function 的 default parameter 或 for, while 有關……


這裡解釋得滿清楚的︰
http://exploringjs.com/es6/ch_variables.html

如果看了這一堆還很有興趣的話,可以玩這個︰
http://perfectionkills.com/javascript-quiz-es6/
Javascript quiz. ES6 edition. — Perfection Kills
Javascript rants and findings, by kangax ...

 

--
                                      ▏                                      
                                      ▏                                      
                                   ◣                                  
                                  ▄▆                                
                                  ◥    ◤                                
                                   ▄                                         

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.250.156.252
※ 文章代碼(AID): #1OgRYik4 (Ajax)
※ 文章網址: https://www.ptt.cc/bbs/Ajax/M.1487517868.A.B84.html
violet90079: 感謝指點~~JavaScript真的好深奧啊Orz1F 02/19 23:58
MangoTW: 推精闢解析2F 02/20 00:25
broo: 多謝解說!有了解一些了!3F 02/20 23:48

--
※ 看板: terievv 文章推薦值: 0 目前人氣: 0 累積人氣: 101 
作者 eight0 的最新發文:
點此顯示更多發文記錄
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇
看板名稱: 確定(Enter) 取消(Esc) 搜尋(Space)
查詢帳號: 確定(Enter) 取消(Esc) 搜尋(Space)
搜尋: m)m文 b)進板 c)未分類 a)作者 /)標題 q)取消?[q]

搜尋 送出(Enter) 取消(Esc)

回覆文章至: f)看板 m)作者信箱 b)兩者皆是 q)取消?[f]
要引用原文嗎? y)引用原文 n)不引用 a)全部回覆 r)複製原文 q)取消?[y]
轉錄本文章於看板: 1)使用連結 2)使用複製 q)取消 ?[1]
轉寄至站內信箱於使用者: 確定(Enter) 取消(Esc)
轉寄至站內信箱於使用者: 確定(Enter) 取消(Esc)
修改文章標題為: 確定(Enter) 取消(Esc)
修改文章標題為: 確定(Enter) 取消(Esc) 全部(a)

確定要刪除這篇文章?(可按大U救回) 確定(Enter) 取消(Esc)

刪除理由:

確定(Enter) 取消(Esc)
加到這個分類: 確定(Enter) 下一層(→) 回上層(←) 取消(Esc)
你覺得這篇文章: 1)真讚 2)真瞎 q)取消?[1] (再選一次即可收回)
你覺得這篇文章: 1)值得推薦 2)表示反對 3)單純註解 q)取消?[3]
guest
預覽(Enter) 取消(Esc)
上傳圖片
按ctrl+Enter可輸入下一行。
guest
確定要送出? 確定(Enter) 取消(Esc) 繼續(e)
搜尋: 送出(Enter) 取消(Esc)

▏▎▍▌▋▊▉ 請按任意鍵繼續