Javascript原型模式總結梳理


  在大多數面向對象語言中,對象總是由類中實例化而來,類和對象的關系就像模具跟模件一樣。Javascript中沒有類的概念,就算ES6中引入的class也不過是一種語法糖,本質上還是利用原型實現。在原型編程語言中,類並不是必需的,對象不一定需要由類實例化而來,而是通過克隆另外一個對象來得到。

  原型模式是用來創建對象的一種模式。在以類為中心的語言中,要創建一個對象首先要指定這個對象的類型,然后實例化一個對象。使用原型模式創建對象時不必關心對象的具體類型,而是找到一個對象,然后通過克隆來創建一個一模一樣的對象。所以在前者中如果要根據一個對象創建多個相同的對象,我們需要先保存這個對象的所有屬性信息,然后將屬性信息設置到新創建的對象上,而在原型模式中我們只需要使用克隆就能完成同樣的功能。

  在某些玄幻小說中經常會出現某些修真大能,以分身的形式游走世間。這個過程很適合原型模式的應用:

function Master(){
    this.blood = 100;
    this.level = 6;
}

var noumenon = new Master();
noumenon.level = 9;


var ektype = Object.create(noumenon);

console.log(ektype);

  ES5提供了原生的克隆方法:Object.create,不支持這個方法的瀏覽器可以使用如下代碼:

function clone(obj){
    function F(){};
    F.prototype = obj;
    return new F();
}

var ektype = clone(noumenon);

  通過以上代碼,我們看到了如何通過原型模式來克隆出一個一模一樣的的對象。原型模式的真正意義並非創建一個一模一樣的對象,而是提供一種創建對象的方式,Javascript的面向對象機制是基於原型模式的,他的對象系統就是使用原型模式,通過克隆來創建的,克隆是創建一個對象的過程和手段。以繼承為例:

function Person(name){
    this.name = name;
}

function Developer(lang){
    this.language = lang;
}

var p = new Person('coder');

Developer.prototype = p;

var dev = new Developer('Javascript');

 

  基於原型的繼承體系,子類的每次實例化都是對其構造函數的prototype屬性的克隆。所以每次創建Developer對象,其實都是在對p對象的克隆。

  在Java等以類為中心的面向對象語言中,經常使用new實例化一個對象。但是Javascript是基於原型的面向對象語言,在這里new運算符創建對象的方式與Java中的new運算符並不相同,Javascript中的new運算符也是通過克隆來實例化對象的,克隆的是構造器函數的原型對象,new運算符的作用等同於如下代碼:

function Person(name){
    this.name = name;
}

function Developer(lang){
    this.language = lang;
}

var p = new Person('coder');

Developer.prototype = p;


function _new(_Constructor) {
    var that = Object.create(_Constructor.prototype);
    var args = Array.prototype.slice.call(arguments, 1);
    var other = _Constructor.apply(that, args);
    
    return (typeof other === 'object' && other) ? other : that;
}
_new(Developer, 'JavaScript')

  從這我們也可以看出,Javascript的原型實際上存在着諸多矛盾,它的某些復雜語法看起來就像那些基於類的語言,這掩蓋了它的原型機制。所以jQuery中盡量避免使用new運算符來創建對象。

  根據前面所說Javascript中新創建的對象都是基於原有對象的克隆,所以在Javascript中存在一個最原始的對象:Object.prototype,所有對象都是由它克隆而來。

 

  這里所說的克隆是在Javascript原型模式這一大環境下的一種語義表達,在計算機的物理世界中並不存在真正的克隆。所以這里對於克隆應當理解為產生一個擁有__proto__屬性指向原對象的對象的過程,原對象成為被克隆的對象,也就是構造函數的prototype對象。

 

  擁有以上共識后,我們可以得到在Javascript中原型編程的基本規則:

  1. Javascript中絕大多數數據都是對象
  2. 要得到一個對象,不是通過實例化類,而是找到一個對象作為原型並克隆它
  3. 對象會記住它的原型
  4. 如果對象無法響應某個請求,他會把這個請求委托給它自己的原型

 

參考書籍:

《Javascript語言精粹》

《Javascript設計模式與開發實踐》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM