1. 程式人生 > >javaScript設計模式之面向對象編程(object-oriented programming,OOP)(一)

javaScript設計模式之面向對象編程(object-oriented programming,OOP)(一)

email 全局變量 color javascrip 原型 obj 只有一個 沒有 ted

面試的時候,總會被問到,你對javascript面向對象的理解?

面向對象編程(object-oriented programming,OOP)是一種程序設計範型。它講對象作為程序的設計基本單元,講程序和數據封裝其中,以提高程序的重用性、靈活性和擴展性。

一、舉個例子

有這麽一個需求:做一個驗證表單功能,僅需要驗證用戶名,郵箱,密碼等

覺得在項目產品開發中,自己是這麽寫的

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

聲明了3個全局變量,

下面是創建3個函數保存在變量裏來實現你的功能,而你寫的是將你的變量名放在function後邊,也代表了你的變量,所以聲明了3個全局變量。

//創建了3個函數保存在變量裏
var checkName = function(){
    //驗證姓名
}
var checkEmail = function(){
    //驗證碼郵箱
}
var checkPassword = function(){
    //驗證密碼
}

從功能上講沒有任何問題,但是如果別人也定義了同樣的方法就會覆蓋原有的功能,這種相互覆蓋的問題不易覺察到。

我們可以將這些檢查函數放在一個變量裏保存,這樣減少覆蓋和被覆蓋的風險。

(1)用對象收編變量

對象,他有屬性和方法,我們訪問屬性或者方法,可以通過點語法向下遍歷查詢得到,我們可以創建一個檢測對象,我們把方法放在裏面。

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

這個時候我們將所有的函數作為CheckObject對象的方法,這樣我們就只有一個對象,比如檢測姓名CheckObject.checkName().

(2)對象的另一種形式

首先聲明一個對象,然後給他添加方法,在JavaScript中函數也是對象。

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

但是當別人想用你寫的對象方法就比較麻煩,因為這個對象不能復制一份(這個對象類在用new關鍵字創建新的對象時,新創建的對象時不能繼承這些方法)

(3)真假對象

如果想簡單的復制一下,你可以將這些方法放在一個函數對象中。

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

當每次調用這個函數的時候,把我們之前的對象返回出來,當別人每次調用這個函數時都會返回新對象。這樣我們每個人使用的時候就不會相互影響,比如檢測郵箱可以這樣:

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

(4)類也可以

雖然通過創建新對象完成需求,但是他不是一個真正的意義上的類的創建方式,並且創建對象a和對象CheckObject沒有任何關系,返回的對象與CheckObject對象無關,稍微優化一下。

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

上面的這樣的對象,就可以看成是類,我們就可以不需要使用創建對象方法創建,既然是一個類,就用關鍵詞new來創建

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

這樣就可以用CheckObject類創建出來對象,我們其他人就可以對類實例化(用類創建對象),這樣每一個人都有一套自己的方法。

(5)一個檢測類

通過this的定義,每一次通過new關鍵字創建新對象時候,新創建的對象都會對類的this上的屬性進行復制,所以新創建的對象都會有自己的一套方法,然而有時候造成消耗很奢侈,我們需要處理一下。

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

這樣創建對象實例時候,創建出來的對象所擁有的方法都是一個,因為他們需要依賴prototype原型依次尋找,而找到方法是同一個,但是prototype寫很多遍,可以這麽寫

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

以上兩種方法不能混著用。

如在後邊為對象的原型對象賦值新對象,那麽會覆蓋之前對prototype對象賦值的方法。

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

(6)方法還可以這樣用

1、this對象

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

使用:

CheckObject.checkName().checkEmail().checkPassword();

2、類的原型對象

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

但是使用的時候需要創建一下

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

(7)函數祖先

比如你想給每一個函數都添加一個檢測郵箱的方法。

Function.prototype.checkEmail = function(){
    //檢測郵箱

這樣使用這個方法就比較簡單,

1、函數形式

var f = function(){};
f.checkEmail();

2、類的形式

var f = new Function();
f.checkEmail();

你這種方式,原則上沒有問題,但是汙染了全局原生對象Function,這樣別人創建的函數也會被你創建的函數汙染,造成不必要的開銷,但是你可以抽象出一個統一添加方法的功能方法。方法如下:

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

這個時候,如果你想添加郵箱驗證的方法和姓名驗證的方法,可以這樣使用

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

(8)鏈式添加

如果想鏈式添加,在addMethods中將this返回,就可以

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

如果你還想添加方法,可以這樣:

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

如果我想鏈式使用,應該如何實現?

既然添加方法可以將this返回實現,那麽添加的每一個方法都將this返回是不是也就實現了呢?

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

測試一下:

methods.checkName().checkEmail();

(9)換一種使用方式

1、函數式調用

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

2、類式調用

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

使用類式調用,不能直接使用,需要通過new關鍵字來創建新對象

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

JavaScript中函數時一等公民。

1、如何實現方法的鏈式調用?

只需在類中的每個方法中通過this關鍵字返回對象實例的引用。每次函數調用都會返回一個新對象,表面上是CheckObject對象,實際是返回的新對象,這樣每次調用就不會相互影響了。

2、為函數添加多個方法的addMethod方法?

(1)this對象

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

(2)類的原型對象

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

javaScript設計模式之面向對象編程(object-oriented programming,OOP)(一)