IT 行業對JavaScript開發者有著很大的需求。如果你具備這種角色所需的知識結構,那麼你就有很多的機會來影響你的公司,提高你的工資。但是在你被一家公司僱傭之前,你需要展示自己的技能以便通過它們的面試。在這篇文章中,我將列出5個典型的常用於測試候選人的JavaScript技能的問題。
問題1:作用域
考慮如下程式碼:
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) {/* code here */}; |
當你被問起去擴充套件一個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)); |
小結
本文我們討論了5個在對Javascript開發者面試中常問起的典型問題。實際中的問題會因面試的不同而不同,但是所涉及的概念和主題通常很類似。我希望你在檢測自己的知識中獲得樂趣。如果你不知道其中一些問題的答案,不要擔心:沒有什麼是學習和試錯不能夠彌補的。如果你曾在面試中被問過其他的一些有趣的問題,不要猶豫,跟我們分享吧,它會幫助很多的開發者。