1、js設計模式-對症下藥

一、一個郵箱驗證的功能函數的寫法有幾種?

(1) 簡單的寫法函數

function checkName(){};
function checkEmail(){};
function checkPassword(){};

分析:這幾個函數能夠認爲是幾個全局變量,相似於this

var checkName = function(){};
var checkEmail = function(){};
var checkPassword = function(){};

使用場景:適用於功能比較單1、獨立的邏輯prototype

優勢:寫法、用法都比較簡單code

缺點:此時的函數做爲全局變量存在,在這種狀況多的時候團隊開發時容易被別人的變量覆蓋,並且從業務上講這幾個屬於一類函數,因此放在一個對象裏的話代碼的可讀性大大提升對象

(2) 做爲一個對象的一個屬性的函數內存

一、 var CheckoutObject = {
      checkName: function(){},
      checkEmail: function(){},
      checkPassword: function(){},
    };

相似於開發

二、var CheckoutObject = function(){};
    CheckoutObject.checkName = function(){};
    CheckoutObject.checkEmail = function(){};
    CheckoutObject.checkPassword = function(){};

使用場景:幾個功能有必定的邏輯或者類別上的關係,例如對錶單的增刪改查都屬於對錶單的操做rem

分析以及優勢:這兩種方式都只有一個全局變量,極大了削弱了命名衝突的隱患,都能直接經過變量名稱CheckoutObject直接使用方法,區別是2屬於函數,在函數內部能夠定義全部實例共有的屬性,更加符合類的特色,更加具體的說1是2的一種語法糖、只是2的一種實現方法原型

缺點:1不太符合類的特色不能去實例化,雖然2能夠經過new去建立對象可是建立的對象並不包括那些靜態方法,對於函數變量CheckoutObject複用性比較差,並且包含屬性並不獨立
(3) 函數返回對象,該對象包含郵箱校驗的方法io

var CheckoutObject = function(){
    return {
      checkName: function(){},
      checkEmail: function(){},
      checkPassword: function(){},
    };
  };
  // 調用方法
  var test = new CheckoutObject();
  test.checkName();
  test.checkEmail();
  test.checkPassword();

使用場景:能夠用來存放一些公共屬性,會被多人調用,每次都生成新的實例

分析:構造函數返回一個對象,對象包含所需的屬性,每次new都是一個新對象,對象包含校驗須要的屬性

優勢:每一個實例對象所包含的屬性都是獨立的

缺點:test的對象和CheckoutObject沒什麼關係,經過instanceof檢測不出來,

(4) 更具備類特色的對象

var CheckoutObject = function(){
  this.checkName = function(){};
  this.checkEmail = function(){};
  this.checkPassword = function(){};
};
var test = new CheckoutObject();
console.log(test instanceof CheckoutObject); // true

特色:實例對象的類型是構造函數,這樣更適用於封裝
(5) 對象間共享的方法
分析:上述建立的對象都是獨立的擁有本身的屬性,可是這些屬性是相同的,這樣形成了內存的浪費

var CheckoutObject = function(){};
CheckoutObject.prototype.checkName = function(){
  console.log('我叫小將');
};
var test1 = new CheckoutObject();
var test2 = new CheckoutObject();
test1.checkName(); // 我叫小將
test2.checkName(); // 我叫小將
console.log(test1.checkName === test2.checkName); // true

使用場景:各個實例都擁有這個屬性,這樣就能夠提取到原型對象中,減少內存損耗

優勢:原型屬性被全部屬性所共享

缺點:實例的屬性缺少獨立性,因此獨立屬性和共享屬性應該對症下藥

(6) 更簡單的鏈式調用

分析:好的代碼應該精簡,能佔一行毫不佔兩行

var CheckoutObject = {
  checkName: function(){ return this },
  checkEmail: function(){ return this }
}
CheckoutObject.checkName().checkEmail()

共享的也能夠

var CheckoutObject = function(){};
CheckoutObject.prototype.checkName = function(){
  console.log(this);
  return this;
};
CheckoutObject.checkName()

使用場景:適合一系列操做,例如本博文的校驗

優勢:調用方式簡潔,易懂

缺點:每一個函數都必須返回當前this,也就是this必須指向當前執行環境

二、原生對象(例如Array)添加獨立的方法

爲原生對象添加屬性一般是經過原型對象

Array.prototype.remove = function(){};

缺點:全部Array都具備了這個remove屬性形成了污染
優勢:若是大部分實例都須要這個方法這就成了優勢了

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

這樣全部的Array都具備addMethod這個屬性,可是具體添加的方法是每一個實例所共有,具體用那種看實際使用場景,並且能夠在addMethod函數內加一些其它的共享屬性

鏈式添加和使用

Function.prototype.addMethod = function(name, fn){
  console.log(this === Method);
  this.prototype[name] = fn;
  return this;
};
var Method = new Function();
Method.addMethod('checkName', function(){
  console.log('姓名檢查');
  return this;
}).addMethod('checkEmail', function(){
  console.log('郵箱檢查');
  return this;
})

var method = new Method();
method.checkName().checkEmail();

使用場景:爲原型對象添加共享方法,可是具體執行每一個原型實例能夠本身定義

優勢:提供共享的添加函數,具體添加的函數每一個Method獨立,method再次共享

總結:綜上能夠看到每種方式都有其使用場景,要對症下藥選擇最合適的模式

相關文章
相關標籤/搜索