天天看點

5個典型的JavaScript面試題(上)

考慮如下代碼:

1 2 3 4 5 6 7

(

function

() {

var

a = b = 5;

})();

console.log(b);

請問控制台上會輸出什麼?

答案

輸出:5

這一題的陷阱是,在函數表達式中有兩個指派,但a是用關鍵字var 來聲明的,這意味着a是局部變量,而b則被賦予為全局變量。

另一個陷阱是,它并沒有使用嚴格模式(use strict)。在函數裡面,如果啟用了嚴格模式,代碼就會報錯:“Uncaught ReferenceError: b is not defined”。請記住,嚴格模式需要你顯式地引用全局作用域,代碼應該寫成:

1 2 3 4 5 6 7 8 9

(

function

() {

'use strict'

;

var

a = window.b = 5;

})();

console.log(b);

問題2:建立“内置”方法

給String對象定義一個repeatify方法。該方法接收一個整數參數,作為字元串重複的次數,最後傳回重複指定次數的字元串。例如:

1

console.log(

'hello'

.repeatify(3));

輸出應該是

1

hellohellohello.

答案

一個可行的做法如下:

1 2 3 4 5 6 7 8 9 10 11 12 13

String.prototype.repeatify = String.prototype.repeatify ||

function

(times) {

var

str =

''

;

for

(

var

i = 0; i < times; i++) {

str +=

this

;

}

return

str;

};

這題測試開發者對Javascript的繼承及原型屬性的知識,它同時也檢驗了開發者是否能擴充内置資料類型的方法。

這裡的另一個關鍵點是,看你怎樣避免重寫可能已經定義了的方法。這可以通過在定義自己的方法之前,檢測方法是否已經存在。

1

String.prototype.repeatify = String.prototype.repeatify ||

function

(times) {

};

當你被問起去擴充一個Javascript方法時,這個技術非常有用。

問題3 :聲明提前

下面這段代碼的結果是什麼?為什麼?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

function

test() {

console.log(a);

console.log(foo());

var

a = 1;

function

foo() {

return

2;

}}

test();

答案

代碼的運作結果:undefined和 2

理由是,變量和函數的聲明都被提前至函數體的頂部,而同時變量并沒有被指派。是以,當列印變量a時,它雖存在于函數體(因為a已經被聲明),但仍然是undefined。換句話說,上面的代碼等同于下面的代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

function

test() {

var

a;

function

foo() {

return

2;

}

console.log(a);

console.log(foo());

a = 1;

}

test();

問題4:JavaScript中的this

下面代碼的運作結果是什麼并做解釋。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

var

fullname =

'John Doe'

;

var

obj = {

fullname:

'Colin Ihrig'

,

prop: {

fullname:

'Aurelio De Rosa'

,

getFullname:

function

() {

return

this

.fullname;

}}};

console.log(obj.prop.getFullname());

var

test = obj.prop.getFullname;

console.log(test());

答案

代碼輸出:Aurelio De Rosa 和 John Doe

理由是,Javascript中關鍵字this所指代的函數上下文,取決于函數是怎樣被調用的,而不是怎樣被定義的。

在第一個console.log(),getFullname()被作為obj.prop對象被調用。是以,目前的上下文指代後者,函數傳回這個對象的fullname屬性。相反,當getFullname()被賦予test變量,目前的上下文指代全局對象window,這是因為test被隐式地作為全局對象的屬性。基于這一點,函數傳回window的fullname,在本例中即為代碼的第一行。

問題5:call()和apply()

修複前一個問題,讓最後一個console.log() 列印輸出Aurelio De Rosa.

答案

這個問題可以通過運用call()或者apply()方法強制轉換上下文環境。如果你不了解這兩個方法及它們的差別,我建議你看看這篇文章What’s the difference between function.call and function.apply?. 下面的代碼中我用了call(),但apply()也能産生同樣的結果:

1

console.log(test.call(obj.prop));