JavaScript模式筆記

###JavaScript模式學習筆記

1、基本技巧

  • 儘可能少使用全局變量
  • 使用單一var模式,即在函數頂部只用一個var進行多個變量聲明;
  • 爲了不變量提高,使用單一var模式;
  • for循環時緩存length,提升速度;
  • for循環遍歷數組,for-in遍歷對象;
  • 不要爲內置的構造函數添加原型屬性;
  • 避免使用隱式類型轉換(==),使用===;
  • 避免使用eval();
  • 使用parseInt()時指明轉換的進制數
  • 良好的編碼規範和命名規則
  • 經過良好的註釋提供參考和維護代碼
    註釋eg:
/**
 * [function description]  函數功能描述
 * @constrctor 用於表示構造函數
 * @namespace namespaceName 用於命名包含全部對象的全局引用的名稱
 * @method methodName 定義對象中的方法和方法名
 * @property propertyName 定義對象中的屬性名
 * @param  {[type]} paramName   [description]  參數
 * @param  {[type]} paramName   [description]  參數
 * @return {[type]}             [description]  返回值
 */

2、字面量和構造函數

  • 可重用的屬性和方法都應該放入原型中。
  • 建立對象和數組時使用字面量語法。
  • 安全的數組檢測:
/**
 * 安全的數組檢測
 * @param  {unknown}  value 待檢測數據
 * @return {Boolean}       是否爲數組
 */
function isArray(value) {
    if(typeof Array.isArray === 'undefined') {
        return Object.prototype.toString.call(value) === '[object Array]';
    } else {
        return Array.isArray(value);
    }
}

3、函數

  1. 即時函數
(function(){
    // dosomething
})();

var fnName=function(){
    alert('Hello World');
}();
//函數表達式後面加括號,當javascript引擎解析到此處時能當即調用函數
function fnName(){
    alert('Hello World');
}();
//不會報錯,可是javascript引擎只解析函數聲明,忽略後面的括號,函數聲明不會被調用
function(){
    console.log('Hello World');    
}();
//語法錯誤,雖然匿名函數屬於函數表達式,可是未進行賦值操做,
//因此javascript引擎將開頭的function關鍵字當作函數聲明,報錯:要求須要一個函數名

即時函數能保證全局空間不會被臨時變量所污染。javascript

  1. 即時對象初始化
({
    //配置常數
    width:600,
    height:600,
    // 定義方法
    gimmeMax: function() {
        return this.widht + "x" + this.height;
    },
    // 初始化
    init: function() {
        console.log(this.gimmeMax());
    }
}).init();
  1. 初始化時分支
    eg: 優化事件綁定
// 這樣只會在初始化EventUtil時執行條件語句,在綁定事件時不用每次都執行條件查詢
var EventUtil = {
    addEvent: null
};
if(typeof window.addEventListener === 'function') {
    EventUtil.addEvent = function(el, type, handler) {
        el.addEventListener(type, handler, false);
    }
}else if(typeof document.attachEvent === 'function') {
    EventUtil.addEvent = function(el, type, handler){
        el.attachEvent('on' + type, handler);
    }
}
  1. 配置對象java

    當函數的參數過多時,爲了提供更整潔的API接口,能夠安全忽略可選參數,更加易於閱讀和維護,易於添加和刪除參數,便可以使用參數對象。設計模式

addPerson(obj){
        // do something...
    }
    var conf = {
        name: "batman",
        firstName: "chris",
        lastName: "bale"
    };
    addPerson(conf);
  1. 函數柯里化數組

    當發現調用同一個函數,且傳遞的參數絕大多數是相同的時候,就能夠對該函數使用柯里化。緩存

function schonfinkelize(fn) {
    var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
    return function() {
        var new_args = slice.call(arguments),
            args = stored_args.concat(new_args);
        return fn.apply(null, args);
    };
}
function add(a, b, c, d, e) {
    return a + b + c + d + e;
}
// 使用示例:schonfinkelize(add, 1, 2, 3)(5, 5);
// 輸出16

4、對象建立模式

  1. 命名空間模式
    建立一個全局對象,而後使全部函數和變量成爲該全局對象的屬性和方法。
var MYOBJ = MYOBJ || {}; // 全局變量所有用大寫形式命名
// 避免重複命名的命名函數
MYOBJ.namespace = function (nameString) {
    var parts = nameString.split('.'),
        parent = MYOBJ,
        i;
    if(parts[0] === "MYOBJ") {
        parts = parts.slice(1);
    }
    for(i = 0; i< parts.length; i++) {
        if(typeof parent[parts[i]] === 'undefined') {
            parent[parts[i]]={};        
        }
        parent = parent[parts[i]];
    }
    return parent;
}
  • 優勢:能夠避免過多的全局變量,避免命名衝突。
  • 缺點:每一個函數變量前面都必須加前綴,增長代碼量,任何代碼均可以修改該全局實例。

依賴關係
在函數或者模塊頂部顯式地聲明依賴的模塊。安全

var function myFunction() {
        //聲明依賴
        var event = MYOBJ.event;
        // 使用依賴關係
        // do something
    }
  1. 私有屬性和方法
//   將私有方法揭示爲公有方法
    var myarray;  
    (function(){
        // 私有屬性
        var astr = '[object Array]'
        // 私有方法
        function isArray(a) {
            return Object.prototype.toString.call(a) === astr;
        }
    // 公共接口
    myarray = {
        isArray: isArray    
    }
    })();
  1. 模塊模式
    結合命名空間使用:
var MYOBJ = MYOBJ || {};
    MYOBJ.namespace('MYOBJ.util.array');
    MYOBJ.util.array = (function(){
        // 私有屬性
        var astr = '[object Array]';
        // 私有方法
        function isArray(a) {
            return Object.prototype.toString.call(a) === astr;
        }
        // 公共接口
        return {
            isArray: isArray    
        };
    })();

5、代碼複用模式

  1. 類式繼承模式
  • 默認繼承模式:
function inherit(Child, Parent) {
        Child.prototype = new Parent();
    }
  • 構造函數繼承模式app

    缺點是沒法從原型中繼承任何方法。優勢是能夠得到父對象自身成員的真實副本,並不會存在子對象意外覆蓋父對象的風險。函數

  • 組合繼承模式學習

    組合繼承模式缺點是父構造函數被調用了兩次,效率低下,且自身的屬性會經過構造函數和原型繼承兩次。優化

  • 共享原型模式
function inherit(Child, Parent) {
        Child.prototype = Parent.prototype;
    }

與默認方法相比,這樣作的優勢是效率比較高(不用執行和創建Parent的實例了),比較省內存。缺點是 Parent.prototype和Child.prototype如今指向了同一個對象,那麼任何對Child.prototype的修改,都會反映到Parent.prototype。

  • 臨時構造函數
function inherit(Child, Parent) {
        var F = function () {}; // 臨時構造函數
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.uber = Parent.prototype; // 儲存超類
        Child.prototype.constructor = Child; // 重置構造函數指針
    }

2.原型繼承(無類繼承模式)

function object(parent){
        function F() {};
        F.prototype = parent;
        return new F();
    }
    var parent = {
        name: "daddy"
    };
    var child = object(parent);

這種繼承方式會共享相應的值,就像默認模式同樣,對子類型的修改都會反應到父類型上。

  1. 寄生繼承
function createAnother(parent){
        var child = object(parent);
        return child;
    }

適合對象不是自定義類型和構造函數的狀況。

  1. 寄生組合式繼承(引用類型最理想的繼承範式!)

    在組合式繼承的基礎上優化,利用寄生繼承繼承父類的原型,使得繼承時只調用一次父類構造函數。

function inheritPrototype(child, parent){
        // ES5有原生object.create方法代替object方法
        var prototype = object(parent.prototype);
        prototype.constructor = child;
        child.prototype = prototype;
    }

// 在組合繼承時將child.prototype = new Parent(); 改爲inheritPrototype(child, parent);

6、設計模式

  1. 單體模式
    單體模式的定義是產生一個類的惟一實例.
var singleton = function( fn ){
    var result;
    return function(){
        return result || ( result = fn .apply( this, arguments ) );
    }
}
var createMask = singleton( function(){
    return document.body.appendChild( document.createElement('div') );
});
  1. 模塊模式
var myNamespace = (function () {
  var myPrivateVar, myPrivateMethod;
  // A private counter variable
  myPrivateVar = 0;
  // A private function which logs any arguments
  myPrivateMethod = function( foo ) {
      console.log( foo );
  };
    return {
        // A public variable
        myPublicVar: "foo",
        // A public function utilizing privates
        myPublicFunction: function( bar ) {
      // Increment our private counter
      myPrivateVar++;
      // Call our private method using bar
      myPrivateMethod( bar );
    }
  };
})();

模塊模式相對於真正的封裝概念更清晰,其次,模塊模式支持私有數據-所以,在模塊模式中,公共部分代碼能夠訪問私有數據,可是在模塊外部,不能訪問類的私有部分。 模塊模式的缺點是由於咱們採用不一樣的方式訪問公有和私有成員,所以當咱們想要改變這些成員的可見性的時候,咱們不得不在全部使用這些成員的地方修改代碼。

相關文章
相關標籤/搜索