JavaScript排坑指南(三)
JavaScript總是給人以驚喜,學習不止,進步不斷,今天繼續補充JS容易搞錯的幾道筆試/面試題,為了秋招繼續努力,歡迎一起為秋招努力的小夥伴共勉
--------------------------------------總部傳送門-----------------------------------
”老生常錯“的this與作用域相關
Q1. 下面程式的輸出結果是?
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);
複製程式碼
output:
10
2
複製程式碼
這個我做錯在第二個輸出上,其實對this
瞭解後就知道,第一個輸出10
應該是很顯然的:雖然在程式執行時,使用了obj.method
方法,讓this指向了obj
,但是真正的函式執行在函式體內部,也即當fn()
執行的時候,this
是指向window
的,所以第一次執行結果是10
那麼這裡第二次執行arguments[0]
為什麼結果是2
?
分析下在method(fn,1)
執行時,經歷了什麼: 首先兩個引數fn
和1
會被放入arguments
中,在arguments
中第一個引數就是我們傳入的函式;接下來fn
執行,此時this
沒有繫結因此指向window
,輸出10
。 然而到了arguments[0]()
這一句,相當於把arguments[0]
中的第一個引數拿來執行, 效果如下:
arguments[0]() //執行,等同於下面的
arguments.0() //當然這句話是不合法的,但是這樣我們可以更清楚知道,this是指向arguments例項本身
複製程式碼
arguments.length
就是它本身的長度(arguments是一個類陣列,具有length屬性),因此輸出2
Q2. try..catch程式的輸出結果
(function () {
try {
throw new Error();
} catch (x) {
var x = 1, y = 2;
console.log(x);
}
console.log(x);
console.log(y);
})();
複製程式碼
輸出結果:
1
undefined
2
複製程式碼
我們都知道var
是在預編譯階段會有一個變數提升,這種型別很容易解決,但是當遇到在catch(x)
中與已有變數重名的情況,一定要區分兩者之間的關係。
用變數提升的方法,把程式重寫並分析如下:
(function () {
var x,y; // 外部變數提升
try {
throw new Error();
} catch (x/* 內部的x */) {
x = 1; //內部的x,和上面宣告的x不是一回事!!
y = 2; //內部沒有宣告,作用域鏈向上找,外面的y
console.log(x); //當然是1
}
console.log(x); //只宣告,未賦值,undefined
console.log(y); //就是2了
})();
複製程式碼
這樣子就很清晰,之後注意預編譯的過程,把變數和函式定義進行提升後,進行分析,會清楚很多
Q3. 下面程式的輸出
var x = 21;
var girl = function () {
console.log(x);
var x = 20;
};
girl ();
複製程式碼
輸出:
undefined
複製程式碼
說實話,這個題目我沒做錯,我沒做錯,我沒做錯!
因為和Q2一樣,而且還沒有Q2難,一句話解釋就是: 函式內部變數提升。 相當於
var x = 21;
var girl = function() {
var x;
console.log(x); // undefined
x = 20;
}
}
複製程式碼
那些詭異的邊角知識
Q1. 運算子考點: 下面程式輸出是什麼?
console.log(1 < 2 < 3);
console.log(3 > 2 > 1);
複製程式碼
輸出:
true
flase
複製程式碼
第一個輸出結果是好理解的,主要看下第二個為什麼是false
核心在於js怎麼去解析<
和>
運算子。 在JS中,這種運算子是從左向右運算的,所以3>2>1
就被轉換成了true>1
,而true
的值是1
,接著比較1>1
就返回false了。
Q2. typeof,下面輸出結果是什麼
console.log(typeof typeof 1);
複製程式碼
答案是string
會輸出string
,這個題目不僅僅是typeof的考察,也是對js運算的一個考察。 在js中一般有兩種操作
- 賦值操作,例如
a = b
2>3
之類的,上面的題目提到過,是從左向右的順序 - 取值操作, js問記憶體:
有沒有見過這個傢伙?
,比如console.log(a)
typeof a
都屬於這個型別,是從右向左的
因此,這個題就被分解為typeof 1
返回"number"
,注意是一個字串。 接下來typeof "number"
,返回string
Q3. typeof undefined == typeof NULL
輸出結果是什麼
首先搞清楚兩點:
typeof undefined
輸出是undefined
typeof null
輸出是object
但是,另一方面,因為js對大小寫敏感,null
≠ NULL
,所以``typeof NULL返回
undefined`
結果是: true
Q4. 遞迴設計。 實現一個函式,給該函式一個DOM節點,函式訪問其所有子元素(所有子元素,不僅僅是直接子元素),每次訪問子元素的時候,併為其傳一個callback。
訪問一個DOM tree,是一個經典的深度優先搜尋的演算法
function Traverse(DOM,callback) {
callback(DOM);
var list = DOM.children;
Array.prototype.forEach.apply(list,(item)=>{
Traverse(item,callback); //遞迴
})
}
複製程式碼