函式宣告與變數宣告的提升機制優先順序問題

一個菜鳥的奮鬥史發表於2019-03-11

部落格地址:提升機制

一次群裡的討論引發的思考

問題:以下程式碼會輸出什麼?

var getName = function() {
  console.log(1)
}
function getName() {
  console.log(2)
}
getName()
複製程式碼

開始我以為會是2,因為後面的程式碼會覆蓋前面的,但是答案往往會偏離我們的想法ε=(´ο`*)))唉。看了群裡的大神提了一句:函式提升 優於變數,開始思考提升機制。

函式提升優於變數提升

這句話沒毛病,紅皮書111頁說道:解析器在向執行環境中載入資料時會率先讀取函式宣告,並使其在執行任何程式碼之前可用(可訪問),即函式宣告提升、JavaScript上卷中第40頁提到函式宣告是優於變數提升的。可見程式碼

console.log(getName)
var getName = 1;
function getName() {
  console.log(2)
}
複製程式碼

輸出為函式getName

問題升級

先來看程式碼:

/* 
* 函式宣告優於變數宣告
* 函式表示式會將變數提升,但是程式碼在執行的時候才會被賦值
*/
test();
console.log(test);
function test() {
  console.log('我是函式');
}
console.log(test);
var test = '我是變數';
console.log(test);
var test = function (params) {
  console.log('我是函式表示式');
}
console.log(test);
test();
複製程式碼

這次,我加入了函式表示式,結果如下:

函式宣告與變數宣告的提升機制優先順序問題
解釋:函式宣告優於變數宣告,所以第一個console.log(test)會輸出函式test(),test()輸出'我是函式'。而變數只有當程式碼執行到該語句的時候才會被賦值並且覆蓋記憶體。所以第三個console.log(test)輸出的是變數'我是變數'。最後函式表示式又覆蓋了前面的程式碼,所以最後一個console.log(test)輸出函式表示式test(),test()輸出'我是函式表示式'。

再升一級

這次,我把程式碼順序調換一下

test();
console.log(test);
var test = '我是變數';
console.log(test);
var test = function (params) {
  console.log('我是函式表示式');
}
console.log(test);
function test() {
  console.log('我是函式');
}
console.log(test);
test();
複製程式碼

結果如下:

函式宣告與變數宣告的提升機制優先順序問題

這次我將函式宣告放到了最下面,但是卻沒有最後一次執行test()輸出的卻是我是函式表示式。解釋:函式在提升的時候解析器就已經解析過一遍了,程式碼執行到函式這裡不會再次解析也就不會再次賦值。因此就不會出現覆蓋前面程式碼這一說。

注意:不要學了一點就忘記別的了啊,如果兩個函式名一樣,後面的會覆蓋前面的(認為是在函式解析的時候覆蓋,即提升的時候就覆蓋了)

console.log(test);
function test() {
  console.log('我是函式');
}
console.log(test);
function test() {
  console.log('我是函式表示式');
}
console.log(test);
test();
複製程式碼

結果:

函式宣告與變數宣告的提升機制優先順序問題

望指正

相關文章