JS Day 37: Var, Let and Const, part 2 - Hoisting
Hoisting 提升
Var Hoisting 變數提升
console.log(a); // undefined
var a = 'A';
// ---- 分隔線 ----
// 實際上這段程式碼對編譯器來說是長這樣
var a; // 只有宣告 a 這個變數
console.log(a); // 只有被宣告,但沒有賦予值,自然是 undefined
a = 'A'; // assignment 不會被提升
把上面的例子拆分,這樣子比較好理解。
var a; // 有宣告,但沒有賦予任何值
console.log(a); // a 會是 undefined
使用 var 跟 let 的結果:
console.log(a); // Undefined
var a = 'A';
console.log(b); // ReferenceError: b is not defined
let b = 'B';
console.log(c); // ReferenceError: c is not defined
const c = 'C';
undefined =/= not defined
undefined 在記憶體已經有準備空間給它
not defined 沒有被定義
var 的特性,只要繼替體有準備位置,使用 var
會出現 hoisting (undefined),反之使用 let
& const
則不會出現 hoisting(not defined),因為變數 b
之前不存在,所以會出錯。
提升 & 函式 (Hoisting & Functions)
函式運算式 (Function Declaration)
延續上方,console.log(a)
會是 undefined
alpha(); // 'Alpha calling...', function 會被提升
console.log(a); // undefined, var a 會被提升,但 assignment 不會
var a = 'A';
function alpha() {
console.log('Alpha calling...');
};
// output
// Alpha calling...
// undefined
console.log(a); // function a()
var a;
function a() {
console.log('say a word');
};
為何不是 undefined
? 因為 function 被提升了。
類似範例:
aTest(); // 我被提升了
function aTest() {
console.log('我被提升了');
};
範例1:
var a = 0;
function a() {
return 1;
};
console.log(typeof a); // number
可以這樣解讀範例1:
var a; // 提升
function a() {
return 1;
};
// 初始化, 不會被提升
a = 0
console.log(typeof a); // number
這樣子寫 console 輸出也是 number。
範例2:
// var
var a;
function a() {
return 1;
};
console.log(typeof a); // function
// let
let a;
function a() {
return 1;
};
console.log(typeof a); // 重複宣告 let a
// SyntaxError: redeclaration of let a
函式陳述式 (Function Expression)
console.log(typeof aTest); // undefined
aTest(); // function 沒有被提升,出錯了。
// TypeError: aTest is not a function
var aTest = function hoist() {
console.log('我被提升了');
};
var aTest 有被提升,但是 function 沒有,aTest 沒有被 initialize,所以是 undefined。
//
// var
aTest(); // function 沒有被提升,出錯了。
// TypeError: aTest is not a function
var aTest = function() {
console.log('我被提升了');
};
//
// let
aTest(); // function 沒有被提升,出錯了。
// ReferenceError: can't access lexical declaration 'aTest' before initialization
let aTest = function() {
console.log('我被提升了');
};
//
// const
aTest(); // function 沒有被提升,出錯了。
// ReferenceError: can't access lexical declaration 'aTest' before initialization
const aTest = function() {
console.log('我被提升了');
};
一樣都是 function,怎麼一個有被提升一個沒有呢?
用 let
或 const
宣告 function expression 都會出現很明確的錯誤:ReferenceError: can’t access lexical declaration ‘findProd’ before initialization (暫時性死區 Temporal Dead Zone, TDZ)。
- 函式提升 > 變數提升
- assignment (
=
) 不會被提升 - Function Expression 不會被提升,function declaration 則會
Reference:
ECMAScript 6 入門: let 和 const 命令
重新認識 JavaScript: Day 10 函式 Functions 的基本概念
我知道你懂 hoisting,可是你了解到多深?
Hoisting in JavaScript
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。