hoisting(提升)
直接看一個簡單的範例
什麼都不寫只寫下面這一行會發生什麼事
console.log(b)
這樣會輸出什麼?
他會輸出 b is not defined
那換成下面例子,照理來說應該還是 b is not defined
console.log(b)
var b = 10
但出來結果是 undefined
這現象就叫 hoisting(提升)
上面這段程式碼可以把他想成以下流程(但實際上不是這樣跑,只是比較好理解而已)
var b
console.log(b)
b = 10
變數宣告會出現在第一行,拉上去的感覺,就叫 hoisting(提升)
只有宣告會提升,賦值不會
再一個例子
test()
function test() {
console.log(123)
}
這個例子可以成功輸出 123
宣告一個 function 之前就直接呼叫它
但在某些程式語言是做不到的
最後一個例子
test()
var test = function () {
console.log(123)
}
可能會以為跟剛剛的例子一樣都是可以成功輸出 123
但實際是 test is not a function
在上述例子可以把它拆成兩個
賦值和變數宣告
只有變數宣告可以 hoisting
所以執行看起來像下面這樣
var test
test()
test = function () {
console.log(123)
}
這樣執行 test()
就找不到 function
hoisting 的順序
hoisting 只會發生在它的 scope 裡面
下面程式 a 會印出什麼呢 ?
var a = 'global'
function test() {
console.log(a)
var a = 'local'
}
test ()
實際執行是 undefined
上面程式碼可以看成下面這樣
test 這個 scope 裡面的 var a = 'local'
被提升了
var a = 'global'
function test() {
var a
console.log(a)
a = 'local'
}
那如果再多一個 a 的 function , console.log(a)
又會印出什麼?
hoisting 提升的順序又是什麼 ?
function test() {
console.log(a)
var a = 'local'
function a () {
}
}
出來會是 [Function: a]
改一下順序呢 ?
function test() {
console.log(a)
function a () {
}
var a = 'local'
}
test()
出來還是 [Function: a]
所以 hoisting 的順序 function 佔有優先權
那如果有同樣兩個 function 呢 ?
function test() {
console.log(a)
a()
function a () {
console.log(1)
}
function a () {
console.log(2)
}
var a = 'local'
}
test()
結果是 2
代表比較後面宣告的會蓋掉前面的
下面例子會被蓋掉嗎?
function test(a) {
console.log(a)
var a = 456
}
test(123)
出來 a 還是 123 ,並沒有 hoisting 不會影響到 a 這個變數
那如果是同名的 function 呢 ?
function test(a) {
console.log(a)
function a () {
}
}
test(123)
出來結果是 [Function: a]
被蓋過去了
所以如果是 function 就會被蓋過去
hoisting 優先順序
- function
- arguments 參數
- var
hoisting 的原理為何?從 ECMAScript 下手
可以先做一下,覺得 log 出來的值依序會是什麼 ?
var a = 1;
function test(){
console.log('1.', a);
var a = 7;
console.log('2.', a);
a++;
var a;
inner();
console.log('4.', a);
function inner(){
console.log('3.', a);
a = 30;
b = 200;
}
}
test();
console.log('5.', a);
a = 70;
console.log('6.', a);
console.log('7.', b);
答案
var a = 1;
function test(){
console.log('1.', a); // undefined
var a = 7;
console.log('2.', a); // 7
a++; // 8
var a;
inner();
console.log('4.', a); // 30
function inner(){
console.log('3.', a); // 8
a = 30;
b = 200;
}
}
test();
console.log('5.', a); // 1
a = 70;
console.log('6.', a); // 70
console.log('7.', b); // 200
ECMAScript 是什麼 ?
可以把他當作 JavaScript 所 follow 的一個標準,可以把他當 JavaScript 的聖經
https://www.ecma-international.org/wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf
1999 年出版的第三版,對應比較舊的版本,但都差不多,從舊的版本看比較容易理解一點
ECMAScript 這樣描述
Execution Contexts
When control is transferred to ECMAScript executable code, control is entering an execution context. Active execution contexts logically form a stack. The top execution context on this logical stack is the running execution context.
下面這張圖就是 Execution Contexts 的概念
(來源:https://medium.freecodecamp.org/lets-learn-javascript-closures-66feb44f6a44)