你真的知道JavaScript嗎
JavaScript是一門奇怪的語言,要真正掌握並不容易。廢話不多說,來一個快速測試,5道題目,看看你對JavaScript是否真正掌握。準備好了嗎?開始咯?
題目
No.1
if (!("a" in window)) {
var a = 1;
}
console.log(a);複製程式碼
No.2
var a = 1,
b = function a(x) {
x && a(--x);
};
console.log(a);複製程式碼
No.3
function a(x) {
return x * 2;
}
var a;
console.log(a);複製程式碼
No.4
function b(x, y, a) {
arguments[2] = 10;
console.log(a);
}
b(1, 2, 3);複製程式碼
No.5
function a() {
console.log(this);
}
a.call(null);複製程式碼
解析
題目來自?dmitry.baranovskiy.com/post/914032…
解析加上了自己的理解?
No.1
在瀏覽器環境中,全域性變數都是window
的一個屬性,即var a = 1
等價於 window.a = 1
。in
操作符用來判斷某個屬性屬於某個物件,可以是物件的直接屬性,也可以是通過prototype
繼承的屬性。
再看題目,在瀏覽器中,如果沒有全域性變數 a
,則宣告一個全域性變數 a
(ES5沒有塊級作用域),並且賦值為1。很多人會認為列印的是1。非也,大家不要忘了變數宣告會被前置!什麼意思呢?題目也就等價於
var a;
if (!("a" in window)) {
a = 1;
}
console.log(a);複製程式碼
所以其實已經宣告瞭變數a
,只不過if
語句之前值是undefined
,所以if
語句壓根不會執行。
最後答案就是 undefined
No.2
這道題有幾個需要注意的地方:
- 變數宣告、函式宣告會被前置,但是函式表示式並不會,準確說類似變數宣告前置,舉個例子:
console.log('b', b); // b undefined
var b = function() {}
console.log('b', b); // b function () {}複製程式碼
2.具名的函式表示式的名字只能在該函式內部取到,舉個例子(排除老的IE?):
var foo = function bar () {}
console.log('foo', foo);
// foo function bar(){}
console.log('bar', bar);
// Uncaught ReferenceError: bar is not defined複製程式碼
綜合這兩點,再看題目,最後輸出的內容就為 1
No.3
函式宣告會覆蓋變數宣告,但不會覆蓋變數賦值,舉個例子簡單粗暴:
function foo(){
return 1;
}
var foo;
console.log(typeof foo); // "function"複製程式碼
函式宣告的優先順序高於變數宣告的優先順序,但如果該變數foo
賦值了,那結果就完全不一樣了:
function foo(){
return 1;
}
var foo = 1;
console.log(typeof foo); // "number"複製程式碼
變數foo
賦值以後,變數賦值初始化就覆蓋了函式宣告。這個需要注意
再看題目
function a(x) {
return x * 2;
}
var a;
console.log(a); // function a(x) {...}複製程式碼
No.4
這題考察 arguments
物件的用法(詳看?JavaScript中的arguments物件)
一般情況,arguments
與函式引數是動態繫結關係(為什麼說是一般稍後會解釋),所以很好理解,最後輸出的是10
但是但是但是,我們不要忘了一個特殊情況--嚴格模式,在嚴格模式中 arguments
與相當於函式引數的一個拷貝,並沒有動態繫結關係,舉個例子:
'use strict'
// 嚴格模式!!
function b(x, y, a) {
arguments[2] = 10;
console.log(a);
}
b(1, 2, 3); // 3複製程式碼
No.5
function a() {
console.log(this);
}
a.call(null);複製程式碼
關於 a.call(null);
根據ECMAScript262規範規定:
如果第一個引數傳入的物件呼叫者是null
或者undefined
的話,call
方法將把全域性物件(瀏覽器上是window
物件)作為this的值。所以,不管你什麼時候傳入null
或者 undefined
,其this
都是全域性物件window
。所以,在瀏覽器上答案是輸出 window
物件。
但是但是但是,我們依舊不能忘記一個特殊情況--嚴格模式,在嚴格模式中,null
就是 null
,undefined
就是 undefined
,舉個例子:
'use strict';
// 嚴格模式!!
function a() {
console.log(this);
}
a.call(null); // null
a.call(undefined); // undefined複製程式碼
提醒
- 在瀏覽器中的全域性物件是
window
,Node.js中是global
; - 為了使程式碼更加嚴謹與健壯,建議寫JS都加上嚴格模式
'use strict';
- ES6已經成為前端必備技能,呼籲大家都使用ES6,方便高效,可以使用babel把ES6轉成ES5甚至ES3,儘量使用ES6推動前端的發展?
About
GitHub: ?github.com/microzz
個人網站: ?microzz.com/