javascript
是一門弱語言,他有着分同通常的靈活性使它迅速的成爲幾乎人人必會的一門語言,but,大家使用的姿式真的正確嗎?javascript
在之前的開發過程中,老闆:給我加個驗證用戶郵箱
、驗證用戶短信...
功能!java
function checkMessage(){...}
function checkEmail(){...}
function ... //茫茫多的函數
複製代碼
這樣寫好了以後 function
是全局的變量,那麼是全局的就不免會對項目javascript環境形成污染,可能會對其餘同事形成影響,咱們首先要考慮會不會影響別人,若是別人重名對你的checkMessage
覆蓋,那麼這樣的BUG是很難發現的。爲了避免形成太多的全局污染
,咱們能夠這樣寫:編程
var checkObject = {
checkMessage:function(){},
checkEmail:function(){},
...
}
複製代碼
首先說明,並非這樣寫就不會形成污染了,checkObject
依舊是全局變量,那麼好處在哪裏呢?想一下若是Jquery的$
被覆蓋了,那麼咱們頁面的設計模式
$.each | $.extends | $(#id) | $...
複製代碼
都失效了,那麼咱們很容易定位問題: Jquery
出問題了!checkObject
也是同樣,當checkObject出問題了,咱們很容易定位錯誤。bash
調用:checkObject.checkMessage()
便可函數
那麼問題又來了:若是有同事用個人checkObject搞一些事情呢?它能夠直接用個人方法麼?固然能夠,問題是,你買了一本書你願意別人亂寫亂畫麼?咱們能夠改造一下:ui
var checkObject = function(){
return {
checkMessage:function(){},
checkEmail:function(){},
...
}
}
複製代碼
咱們把方法經過function
的調用返回,這樣別人能夠這樣用 :this
var check = checkObject();
check.checkEmail();
複製代碼
咱們能夠再完善一下,把checkObject
當作java的類,checkMessage
,checkEmail
當作java的public
公有方法,既然當作類了,咱們能夠把checkObject
寫成大寫CheckObject
spa
var CheckObject = function(){
this.checkMessage = function(){},
this.checkEmail = function(){},
...
}
複製代碼
別人調用:prototype
var check = new CheckObject(); //既然是一個類了,就要 new 來實例化了
check.checkEmail();
複製代碼
每一次經過new
建立新對象的時候,新建立的對象都會對類this
上的屬性進行復制,你定義了兩個那麼就複製兩次,那麼再更多呢?是否是感受有些奢侈呢,考慮咱們能夠運用javascript的原型prototype
來建立它:
var CheckObject = function(){
}
CheckObject.prototype.checkMessage = function(){},
CheckObject.prototype.checkEmail = function(){},
...
複製代碼
你嫌麻煩?
var CheckObject = function(){
}
CheckObject.prototype{
checkMessage : function(){},
checkEmail : function(){},
...
}
複製代碼
這樣咱們的方法都複製到CheckObject
的原型連上去了,建立出來的對象都是經過prototype
依次尋找,都綁定在CheckObject
的原型上__proto__
Jquery
的原型鏈,是否是很熟悉的方法呢?
同志們是否好奇Jquery
的方法是如何鏈式調用的呢?很簡單,我來模擬一下
var CheckObject = function(){
}
CheckObject.prototype = {
checkMessage : function(){ ... return this },
checkEmail : function(){ ... return this },
...
var check = new CheckObject();
check.checkMessage().checkEmail();
複製代碼
就這麼簡單,咱們只須要將this
指代的當前對象所有返回便可。
咳咳,言歸正傳,回到面向對象編程的課題上
java中有 private
聲明的私有變量、 有經過public
的getter
setter
方法進行通訊,有static
修飾的靜態變量
,靜態方法
,有構造器
,那麼javascript可使用這樣的設計模式麼?能夠,跟我往下看:
咱們去商店買菸
var Smoke = function(id,name){
//私有屬性
var num = 0;
//對象的公有屬性 (須要new)
this.id = id;
//私有方法
function checkID(){ return true};
//公有 setter getter 構造函數
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name;
}
//對象的公有屬性 (須要new)
this.information = function(){
//只有在Smoke內部才能調用checkID()
if(checkID()) return this.name+'香菸'+'訂單號 :'+this.id
}
}
Smoke.prototype = {
money:'10元', //公有屬性(不須要new) 直接Smoke.money[想沒想到Array的length?]
other:function(){}
}
var smoke = new Smoke(994857,'煊赫門');
smoke.information(); //"undefined香菸訂單號 :994857" ps:由於咱們沒對Smoke的name屬性賦值
smoke.setName('煊赫門'); //咱們賦值
smoke.information(); //"煊赫門香菸訂單號 :994857"
smoke.num; //undefined ps:很明顯他是私有屬性
smoke.checkID();//error is not function ps:很明顯私有方法
複製代碼
若是咱們沒有new
var smoke = Smoke(994857,'煊赫門');
smoke.information(); //Uncaught TypeError: Cannot read property 'information' of undefined
複製代碼
納尼報錯了?
smoke.money; //undefind
smoke //undefind
複製代碼
(好像明白了什麼......) 別急,讓咱們看下window
window.information(); // "undefined香菸訂單號 :994857"
複製代碼
恍然大悟,由於new是能夠對當前對象(Smoke)的this
不停地賦值【上面講過】,而上面的沒有new
至關於全局執行了Smoke()
因此是他的this
指向到 window
去了! 怎麼避免這種無操做呢?咱們在Smoke內部進行類型檢查:
var Smoke = function(id,name){
var num = 0;
function checkID(){ return true};
//判斷this在執行過程當中是否是屬於Smoke,若是是說明是new過的 0.0
if(this instanceof Smoke){
this.id = id;
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name;
}
//對象的公有屬性 (須要new)
this.information = function(){
//只有在Smoke內部才能調用checkID()
if(checkID()) return this.name+'香菸'+'訂單號 :'+this.id
}
}else{
return new Smoke(id,name);//內部從新new一個 0.0
}
}
複製代碼
看完了麼,感受爽不,是否是感受就是在寫java呢,其實javascript就是靈活在這裏,這只是javascript一種經常使用的面向對象設計模式,後面我會將更多的設計模式,這些設計模式都是通過前人無數心血總結出來給咱們的,咱們爲何不用呢?
感謝[他竟然愛吃蟲]
同窗對本文的校對