Skip to content

Latest commit

 

History

History
102 lines (76 loc) · 3.29 KB

File metadata and controls

102 lines (76 loc) · 3.29 KB

Javascript 良好程式收集

1. 只搜尋父類別的屬性

使用 in 搜尋屬性時,會沿著 prototype chain 搜尋。可以加上 hasOwnProperty 方法過濾祖父類別的屬性。

var child = new parent();

for(var prop in child){
    if(parent.hasOwnProperty(child[prop]))
        console.log(prop);
}

2. 將判斷與陳述式結合

JavaScript 的 and 和 or 只要符合條件就不繼續檢查。因此在陳述式前加上或(||)且(&&),能更簡潔地將判斷與陳述式結合。 假設自己寫的 JS 框架使用某個符號(變數)作為簡寫(如 $),但又不想跟其他框架衝突(如 jQuery)時,可以先判斷該符號(變數)是否已存在,存在則沿用舊的,不存在就初始符號(變數)。

(window.$) ? window.$ : jQuery;

上面這種寫法也行但更常看到的是下面這種寫法。

window.$ = window.$ || jQuery;

3. 永遠使用模組建構程式

JavaScript 中沒有真正的模組法,但是我們可以將程式碼包在匿名立即函式(JavaScript 以 function(){} 的作為區塊)裡來達到模組的效果。
常見的 JavaScript 的框架都會使用到模組,避免對全域變數造成影響。

//impress.js
(function(){
    var impress = window.impress = function ( rootId ){
        ...
    };
})();

4. 將全域物件傳入模組

JavaScript 查找變數的規則是,會先從區域變數找起,再往上找,最終查找到全域物件。
將全域變數傳入模組有以下好處:

  • 加快變數查找速度:因為傳入的全域物件參數,已經變成了區域變數了,不會再往上查找。
  • 匯出全域變數:區域變數 window 仍然指向全域物件,因此在 window 變數上新增的屬性依然是全域變數。以後在模組內也能產生全域變數了。
//impress.js
(function(document, window){
    var impress = window.impress = function ( rootId ){
        ...
    };
})(document, window);

5. Underscore 的安全引用物件(保證物件只會被包裏一次)

var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
};

Line1:_(obj)obj 已使用 - 呼叫初始過則直接回傳 obj
Line2:若 this 不是 _ 的實例,則呼叫 _ 包裏 obj 並回傳。
Line3:當呼叫 new _(obj) 時,設定 _wrapped 的屬性為 obj

Line2 的條件式不成立時,會重新綁定 _wrapped

var unobj = _(obj);
unobj._();      // 重新綁定 _wrapped 至 unobj
unobj._(unobj); // 重新綁定 _wrapped 至 unobj

6. Return early

  • 避免多餘運算。
  • 判斷參數是否合理。
function fn(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;  // 若參數不合理,不繼續執行下面的程式,直接回傳。
    ...

7. 傳入的引數判斷

Javascript 是動態語言,所以一個變數可以是任何類型。
動態類型的靈活性會帶來一些反效果。
例如,呼叫函數時,如何確保引數的類型是正確的。

  • 使用 argumemts
    • 使用 arguments.length 在函數式判斷引數數量。