1. 程式人生 > >javascript設計模式 第一章 靈活的javascript

javascript設計模式 第一章 靈活的javascript

設計 rip java con 支持 同事 問題 覆蓋 部分

javascript 設計模式

第1章 靈活的語言--JavaScript

初級程序員接到一個驗證表單功能的任務,需要驗證用戶名、郵箱、密碼等

** 此文章內容大部分來自 《javascript設計模式》一書,請支持正版。**

1.簡單的驗證check.js

代碼如下:

function checkName(){
    //驗證姓名
}
function checkEmail(){
    //驗證郵箱
}
function checkPassword(){
    //驗證密碼
}

這段代碼功能可以實現,但是創建了3個全局變量,這就增加了代碼的脆弱性。可能在的check.js文件中只有這3個變量。如果你引入了別人的類庫,或者你的這個js文件給別人使用的話,就增加了全局變量被覆蓋的可能。可能你覆蓋別人的也可能別人覆蓋你的功能。

2.函數的另一種形式

代碼如下:

var checkName = function(){
    //驗證姓名
}
var checkEmail = function(){
    //驗證郵箱
}
var checkPassword = function(){
    //驗證密碼
}

這種方式多了個變量提升,但是並未改變創建了3個全局變量的問題。

3.用對象收編變量

代碼如下:

var CheckObject = {
    checkName:function(){
        //驗證姓名
    },
    checkEmail:function(){
        //驗證郵箱
    },
    checkPassword:function(){
        //驗證密碼
    }
}

這種對象收編方式大大減少了對象被覆蓋的問題,使用直接CheckObject.checkName() 點的方式就可以。

4.對象的另一種形式

var CheckObject = function(){}
CheckObject.checkName = function(){
    //驗證姓名
}
checkObject.CheckEmail = function(){
    //驗證郵箱
}
checkObject.checkPassword = function(){
    //驗證密碼
}

3和4的這兩種方式還會有問題,當別人想用你寫的對象方法時就會有些麻煩了,因為這個對象不能復制一份,或者說這個對象類在用new

關鍵字創建新的對象時,新創建的對象是不能繼承這些方法。

舉個列子:
A同事寫了個獲取用戶名的操作,B同事感覺默認名字“張三”不合適,他想改為其他的。因為對象只有一份B這樣修改後其他任何人再此使用都可能為“李四”。也就是說很容易覆蓋一個公共的方法。

//獲取用戶名
var MyMethod = {
    getDefaultName:function(){
        var defaultName = ‘張三‘;
        return defaultName;
    },

}
MyMethod.getDefaultName();//張三

//B同事修改了MyMethod
MyMethod.getDefaultName = function(){
    var defaultName = ‘李四‘;
    return defaultName;
}
MyMethod.getDefaultName();//李四

5.真假對象

var CheckObject = function(){
    return {
        checkName:function(){
            //驗證姓名
        },
        checkEmail:function(){
            //驗證郵箱
        },
        checkPassword:function(){
            //驗證密碼
        }
    }
}

這段代碼簡單的復制了一遍對象,每次調用函數的時候,把之前的那個對象返回出來,當別人每次調用這個函數時都返回了一個全新的對象。如:

var a = CheckObject();
a.checkEmail();

其實他不是一個真正意義上類的創建方式,並且創建的對象a和對象CheckObject沒有任何關系,返回出來的對象本身就與CheckObject對象無關。

6.類

var CheckObject = function(){
    this.checkName = function(){
        //驗證姓名
    }
    this.checkEmail = function(){
        //驗證郵箱
    }
    this.checkPassword = function(){
        //驗證密碼
    }
}

var a = new CheckObject();
a.checkEmail();

這樣可以看成一個類,每一次通過new關鍵字創建新對象的時候,新創建的對象都會對類的this上的屬性進行復制,這些新創建的對象都會有自己的一套方法,但是這麽做造成了消耗是很奢侈的,因為每次創建new的時候都會復制CheckObject裏面所有的方法。

7.一個檢測類

var CheckObject = function(){}
CheckObject.prototype.checkName = function(){
    //驗證姓名
}
CheckObject.prototype.checkEmail = function(){
    //驗證郵箱
}
CheckObject.prototype.checkPassword = function(){
    //驗證密碼
}

var CheckObject = function(){}
CheckObject.prototype = {
    constructor:CheckObject,
    checkName:function(){
        //驗證姓名
    },
    checkEmail:function(){
        //驗證郵箱
    },
    checkPassword:function(){
        //驗證密碼
    }
}

使用它們:

var a = new CheckObject();
a.checkName();
a.checkEmail();
a.checkPassword();

這樣創建對象實例的時候,創建出來的對象所擁有的方法就是一個了,因為它們都要依賴 prototype原型依次尋找,而找到的方法都是同一個,它們都綁定在CheckObject對象類的原型上。

8.方法還可以這樣用

上面代碼可以看出來多次使用a這時候我們可以想到鏈接調用,在每個方法的末尾處將當前的對象返回。

var CheckObject = function(){}
CheckObject.prototype = {
    constructor:CheckObject,
    checkName:function(){
        //驗證姓名
        return this;
    },
    checkEmail:function(){
        //驗證郵箱
        return this;
    },
    checkPassword:function(){
        //驗證密碼
        return this;
    }
}

使用它們:

var a = new CheckObject();
a.checkName().checkEmail().checkPassword();

9.函數的祖先

模仿prototype.js的作法為每一個函數添加一個檢測郵箱的方法可以這麽做。

Function.prototype.checkEmail = function(){
    //驗證郵箱
}

使用方式:

var f = function(){};
f.checkEmail();
// 或者使用類的方式
var f= new Function();
f.checkEmial();

這樣做的弊端是汙染了原生對象Function,別人創建的函數也會被創建checkEmail,造成不必要的開銷。使用下面的這種方式:

Function.prototype.addMethod = function(name,fn){
    this[name] = fn;
}

使用方式:

var methods = function(){}
//或者
var methods = new Function();
methods.addMethod(‘checkName‘,funciton(){
    //驗證姓名
});
methods.addMethod(‘checkEmail‘,funciton(){
    //驗證郵箱
});
methods.checkName();
methods.checkEmail();

10.同樣添加鏈式

Function.prototype.addMethod = function(){
    this[name] = fn;
    return this;
}

這樣添加方法就方便了一些

var methods = new Function();
methods.addMethod(‘checkName‘,funciton(){
    //驗證姓名
}).addMethod(‘checkEmail‘,funciton(){
    //驗證郵箱
});

同時被添加的每個方法也可以做鏈式返回

var methods = new Function();
methods.addMethod(‘checkName‘,funciton(){
    //驗證姓名
    return this;
}).addMethod(‘checkEmail‘,funciton(){
    //驗證郵箱
    return this;
});

methods.checkName().checkEmail();

11.使用類的方式來實現

上面是函數式調用,對於習慣類式調用的方法如下:

Function.prototype.addMethod = function(){
    this.prototype[name] = fn;
    return this;
}

使用方式:

var methods = function(){}:
methods.addMethod(‘checkName‘,funciton(){
    //驗證姓名
    return this;
}).addMethod(‘checkEmail‘,funciton(){
    //驗證郵箱
    return this;
});

這裏註意。methods不能直接點出來使用,而是要通過new關鍵字來創建新對象。

var m = new Methods();
m.checkEmail();

javascript設計模式 第一章 靈活的javascript