1 求以下函數的輸出
1.1 考察點: 變量提升、this、作用域
// 考察點 作用域、this、變量提升
var a = 10
function test() {a = 100console.log(a) console.log(this.a) var aconsole.log(a)
}
test()
- 第一個和第三個肯定是100
- 在node環境下,沒有window的概念,因此輸出的是 undefined. (最后答案 100 undefined100)
- 在瀏覽器環境下,在沒用找到this時,會順著作用域鏈找到window,而 window.a =10,因此會輸出 10. (最后答案 100 10 100)
[稍微改進]
var a = 10;
function test(){console.log(a);a = 100;console.log(this.a);var a;console.log(a)
}
test();
- 此時根據與解析,會有如下:
var a = 10;
function test() {// var a;console.log(a);a = 100;console.log(this.a);var a;console.log(a)
}
test();
- 瀏覽器環境下因此答案為:
undefined 10 100
1.2 考察點: 閉包的作用域
(function(){var a = b = 3;
})()
console.log(b); // 3
console.log(a); // a is not defined
- 說明: 在非嚴格模式下面,出現了
var a = b = 3
,實際上是b=3
和var a = b
- 在執行
b=3
時,JS解釋器會自動在當前的全局環境下面掛在一個b屬性,值為3 - 所以會輸出
b=3
和a is not defined
1.3 考察點: 事件循環、單線程異步
for(var i=1 ; i<=3; i++){setTimeout(function(){console.log(i)}, 0)
}
- 答案:
4 4 4
- JS是單線程異步,當遇到異步函數的時候,會將異步函數添加到異步函數隊列中.
- for是同步任務,因此,優先執行了3次循環,然后再執行3次輸出.此時,由于i的值是4 ,故輸出 3個4
[變形]:
for(let i = 1; i<=3; i++){setTimout(function(){console.log(i);}, 0);
}
- 答案:
1 2 3
- 前面和上面一樣的,但執行到輸出i的時候, 由于
let
創建的變量是塊級作用域. - 可以看作是把i 同異步函數一起放在一個塊中,放入異步函數的隊列中.
- 當時間到了從異步隊列中拿出塊來執行
1.4 考察點: 作用域 變量提升 形參實參
function fun(n){console.log(n);var n = 456;console.log(n);
}
var n = 123;
fun(n);
- 根據與解析,函數實際如下
function fun(n){// var n = n;console.log(n);n = 456;console.log(n);
}
var n = 123;
fun(n);
- 答案為:
123 456
[稍微改進一下]
function fun(){console.log(n);var n = 456;console.log(n);
}
var n = 123;
fun(n);
- 答案是:
undefined 456
[再稍微改進一下]
function fun(){console.log(n);n = 456;console.log(n);
}
var n = 123;
fun(n);
- 此時沒用變量提升,答案是
123 456
[再再稍微改進一下]
function fun(){console.log(fun);fun = 456;console.log(fun);
}
fun();
var fun = 123;
- 考察函數的提升和變量的提升,等價于,變量提升的速度快于函數提升
var fun = undefined;
var fun = function (){console.log(fun);fun = 456;console.log(fun);
}
fun();
fun = 123;
- 由于函數的提升比變量的提升慢,因此,在遇到
fun()
時,會先執行console.log(fun)
, - 此時會輸出fun函數
- 然后fun賦值為456,然后的console.log會輸出456
- 故輸出結果為:
[Function fun] 456
[再再再稍微改進一下]
function fun(){console.log(fun);fun = 456;console.log(fun);
}
var fun = 123;
fun();
- 根據 變量提升,改造如下:
var fun = undefined;
var fun = function(){...};
fun = 123;
fun();
- 執行到
fun()
時,由于fun是一個變量,因此會報錯:fun is not a function
[再再再再稍微改進一下]
var fun = 123;
function fun(){console.log(fun);fun = 456;console.log(fun);
}
fun();
- 變量提升改造如下:
var fun = undefined;
var fun = function(){...}
fun = 123
fun();
- 執行到
fun()
時,由于fun是一個變量,因此會報錯:fun is not a function
2. 總結
- 使用var的時候要特別小心,它有一個變量提升…
- 函數也存在變量提升,但是它比變量的提升慢
參考
源代碼