轉載自:http://www.css88.com/archives/7052
問題1: 範圍(Scope) (function() { var a = b = 5; })(); console.log(b); 控制台(console)會列印出什麼。
上述代碼會列印出5。
這個問題的陷阱就是,在立即執行函數運算式(IIFE)中,有兩個賦值,但是其中變數a使用關鍵詞var來聲明。這就意味著a是這個函數的局部變數。與此相反,b被分配給了全域範圍(譯註:也就是全域變數)。 這個問題另一個陷阱就是,在函數中沒有使用”strict 模式” ('use strict';)。如果 strict 模式開啟,那麼代碼就會報錯 ” Uncaught ReferenceError: b is not defined” 。請記住,如果這是預期的行為,strict 模式要求你顯式地引用全域範圍。所以,你需要像下面這麼寫: (function() { 'use strict'; var a = window.b = 5; })(); console.log(b);
問題2: 建立 “原生(native)” 方法 在 String 對象上定義一個 repeatify 函數。這個函數接受一個整數參數,來明確字串需要重複幾次。這個函數要求字串重複指定的次數。舉個例子: console.log('hello'.repeatify(3)); 應該列印出hellohellohello. 一個可行的做法如下: String.prototype.repeatify = String.prototype.repeatify || function(times) { var str = ''; for (var i = 0; i < times; i++) { str += this; } return str; };
這個問題測試了開發人員對 javascript 中繼承及原型(prototype)屬性的知識。這也驗證了開發人員是否有能力擴充原生資料類型功能(雖然不應該這麼做)。 在這裡,另一個關鍵點是,看你怎樣避免重寫可能已經定義了的方法。這可以通過在定義自己的方法之前,檢測方法是否已經存在。 當你被問起去擴充一個Javascript方法時,這個技術非常有用。
問題3: 變數提升(Hoisting) 執行以下代碼的結果是什麼。為什麼。 function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();
這段代碼的執行結果是undefined 和 2。 這個結果的原因是,變數和函數都被提升(hoisted) 到了函數體的頂部。因此,當列印變數a時,它雖存在於函數體(因為a已經被聲明),但仍然是undefined。換言之,上面的代碼等同於下面的代碼: function test() { var a; function foo() { return 2; } console.log(a); console.log(foo()); a = 1; } test();
問題4: 在javascript中,`this`是如何工作的 以下代碼的結果是什麼。請解釋你的答案。 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()方法強制轉換上下文環境。如果你不瞭解這兩個方法及它們的區別,我建議你看看這篇文章 function.call和function.apply之間有和區別?。 下面的代碼中,我用了call(),但apply()也能產生同樣的結果: console.log(test.call(obj.prop));