2013-03-07 40 views
7

JavaScript對象具有「原型」成員來促進繼承。但看起來,即使沒有它,我們也可以生活得很好,我想知道,使用它有什麼好處。我想知道有什麼優點和缺點。爲什麼使用'原型'的JavaScript繼承?

例如,請考慮以下的(這裏jsfiddle):

function Base (name) { 

    this.name = name; 
    this.modules = []; 
    return this; 
} 

Base.prototype = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule"); 
    } 
}; 

function Derived(name) { 
     Base.call(this,name); // call base constructor with Derived context 
} 

Derived.prototype = Object.create(Base.prototype); 

Derived.prototype.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.prototype.initModule.call(this); 
    } 

var derived = new Derived("dname"); 
console.log(derived.name); 
derived.initModule(); 

一個問題是,爲什麼用 '原型' 呢?我們也可以這樣做Derived = Object.create(Base);

例如(jsfiddle):

Base = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule",this.name); 
    }, 
    init: function(name) { 
     this.name = name; 
     this.modules = []; 
    } 
}; 

Derived = Object.create(Base); 

Derived.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.initModule.call(this); 
    } 
Derived.init("dname"); 
console.log(Derived.name); 
Derived.initModule(); 
+3

一個職業是速度:http://jsperf.com/prototype-vs-non-prototype/11 – StuR 2013-03-07 16:16:29

+0

如果你有4級繼承?你會聲明一個newnewnewInitModule方法? – mpm 2013-03-07 16:24:44

+0

@mpm你是對的,是一個錯誤,我編輯了這個 – Lior 2013-03-07 16:43:51

回答

3

如果你不使用原型,那麼每個類都會重新定義方法。也就是說,new Base; new Base; new Base將在第二個示例中創建六個函數。這需要更多的時間和空間。 Derived也將創建自己的功能。

此外,您無法使用原型來即時更改每個實例的方法(或添加新方法),這可能會有幫助 - 特別是在模塊之間。

但是,這並不是說你應該總是使用每種方法的原型。每種情況都不一樣。

prototype還允許您在不創建實例的情況下調用不同上下文中的方法(例如類似於數組的對象上的Array.prototype.forEach.call)。

+0

謝謝!表現似乎是主要問題。但是,你能詳細說明'你不能用原型來改變每個實例的方法嗎?不知道我明白 – Lior 2013-03-07 16:45:41

+0

@Lior我的意思是,如果你定義了方法'Base.init',你不能用'Base.prototype.init'(包括它的任何「子」)覆蓋它。它將使用您最初定義的一個'Base.init'方法,除非您明確地從原型鏈中調用另一個 – 2013-03-07 16:50:29

-2

你不需要原型(恕我直言,這是一個反面)爲OO。

考慮這個繼承:

function SubClass() 
{ 
    var object = {}; 
    object.publicVar = 2; 
    object.publicMethod = function SubClassPubMeth() 
     { 
     return this.publicVar + 2; 
     }; 
    object.poly = function SubClassPoly() 
     { 
     return 'SubClassPoly'; 
     }; 
    return object; 
} 

function Class() 
{ 
    var object = new SubClass(); 
    object.classPublicVar = 3; 
    object.classPublicMethod = 
     function ClassMethod() 
     { 
      return this.publicVar + this.classPublicVar; 
     }; 
    object.poly = function ClassPoly() 
     { 
     return 'ClassPoly'; 
     }; 
    return object; 
} 

似乎適合繼承法案。

還要考慮此爲信息隱藏:

函數類() { 變種對象= {}; object.x = 3; var privateVar = 3; function privateFunction(object) { return object.x + privateVar; }

object.publicFunction = function() 
    { 
    var priv = privateFunction(this); 
    priv += privateVar; 
    privateVar = privateVar + 3; 
    return priv; 
    }; 
return object; 

}

似乎也是做信息隱藏的伎倆(AKA封裝)

需要我多說。

+0

如果你關心性能,那麼當你是子類時,或者你正在創建同一個對象的新實例時,你確實需要原型。 – mpm 2013-03-07 16:28:56

+0

你用Javascript做的事情並不需要太多的處理能力。如果你擔心,那麼你使用Java編寫代碼(例如)。 – 2013-03-07 16:32:14