JavaScript排坑指南(三)
JavaScript總是給人以驚喜,學習不止,進步不斷,今天繼續補充JS容易搞錯的幾道筆試/面試題,為了秋招繼續努力,歡迎一起為秋招努力的小夥伴共勉
--------------------------------------總部傳送門-----------------------------------
1.VK的秋招前端奇遇記(一)
2.VK的秋招前端奇遇記(二)
3.VK的秋招前端奇遇記(三)
4.VK的秋招前端奇遇記(四)
5.番外篇:前端面試&筆試算法 Algorithm
”老生常錯“的this與作用域相關
Q1. 下面程式的輸出結果是?
var length = ;
function fn() {
console.log(this.length);
}
var obj = {
length: ,
method: function(fn) {
fn();
arguments[]();
}
};
obj.method(fn, );
複制代碼
output:
複制代碼
這個我做錯在第二個輸出上,其實對
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[]() //執行,等同于下面的
arguments() //當然這句話是不合法的,但是這樣我們可以更清楚知道,this是指向arguments執行個體本身
複制代碼
arguments.length
就是它本身的長度(arguments是一個類數組,具有length屬性),是以輸出
2
Q2. try..catch程式的輸出結果
(function () {
try {
throw new Error();
} catch (x) {
var x = , y = ;
console.log(x);
}
console.log(x);
console.log(y);
})();
複制代碼
輸出結果:
undefined
複制代碼
我們都知道
var
是在預編譯階段會有一個變量提升,這種類型很容易解決,但是當遇到在
catch(x)
中與已有變量重名的情況,一定要區分兩者之間的關系。
用變量提升的方法,把程式重寫并分析如下:
(function () {
var x,y; // 外部變量提升
try {
throw new Error();
} catch (x/* 内部的x */) {
x = ; //内部的x,和上面聲明的x不是一回事!!
y = ; //内部沒有聲明,作用域鍊向上找,外面的y
console.log(x); //當然是1
}
console.log(x); //隻聲明,未指派,undefined
console.log(y); //就是2了
})();
複制代碼
這樣子就很清晰,之後注意預編譯的過程,把變量和函數定義進行提升後,進行分析,會清楚很多
Q3. 下面程式的輸出
var x = ;
var girl = function () {
console.log(x);
var x = ;
};
girl ();
複制代碼
輸出:
undefined
複制代碼
說實話,這個題目我沒做錯,我沒做錯,我沒做錯!
因為和Q2一樣,而且還沒有Q2難,一句話解釋就是: 函數内部變量提升。 相當于
var x = ;
var girl = function() {
var x;
console.log(x); // undefined
x = ;
}
}
複制代碼
那些詭異的邊角知識
Q1. 運算符考點: 下面程式輸出是什麼?
console.log( < < );
console.log( > > );
複制代碼
輸出:
true
flase
複制代碼
第一個輸出結果是好了解的,主要看下第二個為什麼是
false
核心在于js怎麼去解析
<
和
>
運算符。 在JS中,這種運算符是從左向右運算的,是以
3>2>1
就被轉換成了
true>1
,而
true
的值是
1
,接着比較
1>1
就傳回false了。
Q2. typeof,下面輸出結果是什麼
console.log(typeof typeof );
複制代碼
答案是
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 == 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); //遞歸
})
}
複制代碼