原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questions.mdjavascript
最近將持續翻譯JavaScript面試題,但願對各位有所幫助。 html
(文章中斜體字部分爲譯者添加)java
目錄:
Part 1(事件委託/this關鍵字/原型鏈/AMD與CommonJS/自執行函數)git
變量未聲明 是指給一個變量賦值時,沒有使用var,let,const關鍵字對變量進行聲明。未聲明的變量會被默認定在全局,而非當前做用域中。在嚴格模式中,試圖給一個未聲明的變量賦值時,JS會拋出ReferenceError的異常。就像要避免濫用全局變量同樣,咱們一樣要避免操做未聲明的變量。能夠在操做變量時加入try/catch來捕獲未聲明的變量異常。編程
1 function foo() { 2 x = 1; // 在嚴格模式下將會拋出異常:ReferenceError 3 } 4 5 foo(); 6 console.log(x); // 1
undefined變量則是指一個變量被聲明,可是未被賦值。這種變量的類型也是 undefined。若是將一個沒有返回值的函數執行結果賦值給一個變量的話,這個變量值也會是undefined。若是判斷一個變量值是否是undefined呢?可使用typeof 判斷返回值是否是恆等於(===)字符串 "undefined"。這裏要注意,不能使用雙等號判斷變量是否等於undefined,由於用null去判斷的話也會返回true。(原文意思是 null == undefined 返回的值也是true)數組
1 var foo; 2 console.log(foo); // undefined 3 console.log(foo === undefined); // true 4 console.log(typeof foo === 'undefined'); // true 5 6 console.log(foo == null); // true. 不能這麼去判斷,結果不許確 7 8 function bar() {} 9 var baz = bar(); 10 console.log(baz); // undefined
null值變量是指一個變量被賦值爲null。雖然null的表面意思是空值,可是它和undefined是徹底不同的,由於它已經被賦值過了。若是判斷null值?最簡單的方法就是用恆等於進行判斷。一樣要注意的是,這裏也不能使用雙等號來判斷,緣由和上面同樣,由於undefined判斷也會返回true。 閉包
1 var foo = null; 2 console.log(foo === null); // true 3 4 console.log(foo == undefined); // true.不能這麼去判斷,結果不許確
我有一個我的習慣,就是不會讓變量出現未聲明或者未賦值的狀況。我會在變量聲明的同時給它賦值爲null,哪怕這個變量後續再也不使用。 架構
引用文檔:
https://stackoverflow.com/questions/15985875/effect-of-declared-and-undeclared-variables
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/undefined
閉包是函數和聲明該函數的詞法環境的組合。這裏的語法其實是指語法做用域使用一個變量的位置就是聲明該變量的位置。閉包函數擁有訪問外部函數變量的能力,哪怕外部函數已經執行完畢。(因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露)
爲何要使用閉包?
引用文檔:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36
爲了方便理解這兩個方法,讓咱們分別來看這兩個方法的功能。
forEach
1 const a = [1, 2, 3]; 2 const doubled = a.forEach((num, index) => { 3 // Do something with num and/or index. 4 }); 5 6 // doubled = undefined
map
1 const a = [1, 2, 3]; 2 const doubled = a.map(num => { 3 return num * 2; 4 }); 5 6 // doubled = [2, 4, 6]
因此這兩個方法最主要的區別就在於map會返回一個新數組。若是你須要接收處理結果,而且不修改原始數組,那麼map就是最合適的選擇。若是你只是但願單獨循環一個數組的元素,那麼forEach能夠勝任。
引用文檔:
https://codeburst.io/javascript-map-vs-foreach-f38111822c0f
能夠用在自執行函數中。自執行函數包含一些代碼在本地做用域中,這樣變量就被聲明在本地做用域中,而不會污染全局變量。
1 (function() { 2 // Some code here. 3 })();
做爲一次性使用的回調函數,不須要在其餘地方繼續使用該函數。將回調函數定義在代碼的右側,這樣的代碼看起來總體性與可讀性比較好,同時也不用處處去查找函數的實現體。
1 setTimeout(function() { 2 console.log('Hello world!'); 3 }, 1000);
做爲函數式變成構造器或者Lodash的參數。
1 const arr = [1, 2, 3]; 2 const double = arr.map(function(el) { 3 return el * 2; 4 }); 5 console.log(double); // [2, 4, 6]
引用文檔:
https://www.quora.com/What-is-a-typical-usecase-for-anonymous-functions
之前,我用Backbone來建立個人數據模型,它鼓勵使用面向對象的思想,先建立Backbone模型,而後在把方法加上去。
雖然組件模式仍然很棒,但時至今日,我開始使用基於React/Redux的Flux架構,這是一種鼓勵單向數據流動的函數式編程方式。我將使用普通對象來做爲model層,而後寫一些純工具類的方法來管理這些對象。和其餘的Redux程序同樣,State經過actions和reducers來進行維護,
另外我會盡可能避免使用傳統的繼承。若是非要用,我也會遵循如下規則:these rules