2013-11-27 26 views
1

我定義使用這個(prototype)方法有兩個JavaScript類:Javascript繼承與簡潔的原型賦值語法

function Parent() { 
    this.a = 1; 
} 

Parent.prototype = { 
    hello : function() { 
     return "Hello I'm Parent!"; 
    }, 
    setA : function (a) { 
     this.a = a; 
    } 
}; 

function Child() { 
    this.b = 2; 
} 

Child.prototype = new Parent(); 
Child.prototype.constructor = Child; 

Child.prototype = { 
    hello : function() { 
     return "Hello I'm Child!"; 
    }, 
    setB : function (b) { 
     this.b = b; 
    } 
}; 

我使用這種技術,因爲我覺得標準語法太冗長和稀疏:

Child.prototype.hello = function() {...}; 

Child.prototype.setB = function (b) {...}; 

這裏的問題是,我覆蓋Child.prototype(從Parent繼承)失去.setA()方法(但正確覆蓋.hello())。

合併兩個原型的解決方案?怎麼樣?
這種方法會導致問題嗎?

+0

考慮這個繼承:'Child.prototype =的Object.create(新父());' –

+1

@馬蒂亞斯可以使用的Object.create或一個輔助函數,用於在設置繼承的原型部分時防止創建一個Parent實例,所以它應該是:'Child.prototype = Object.create(Parent.prototype);'您和OP執行它的每個實例特定成員的方式在Child實例中創建一個Child實例(Parent.apply(this,arguments))時,父'this.someting'被放置在Child原型上,並且(如果您正確地做到這一點)立即被遮蔽。或更糟;程序員假定Child有Parent的實例成員,並沒有意識到他們實際上是共享的。 – HMR

回答

1

合併兩個原型的解決方案?

是的。

怎麼樣?

只需編寫一個運行在對象字面上的循環,並將每個屬性合併到原型中。

function inherit(Child, Parent, methods) { 
    var p = Child.prototype = Object.create(Parent.prototype); 
    p.constructor = Child; 
    for (var m in methods) 
     p[m] = methods[m]; 
    return p; 
} 
function Child() { 
    Parent.call(this); 
    this.b = 2; 
} 
inherit(Child, Parent, { 
    hello : function() { 
     return "Hello I'm Child!"; 
    }, 
    setB : function (b) { 
     this.b = b; 
    } 
}); 
+1

爲了完整起見,如果Child實例希望讓'this.a'賦值爲1或者以某種方式重新使用Parent初始化代碼,那麼在Child構造函數體中,你應該有'Parent.apply(this,arguments);'通常這個部分被遺忘,OP的示例代碼不需要它,但我甚至看到,即使Crockford抱怨父代碼在繼承時也沒有被重用,所以值得一提的是它可以被重用。 – HMR

+0

@HMR:謝謝你的提醒,我忘了當無意識地複製粘貼構造函數。當然它應該在那裏! – Bergi

0

這裏有一個例子,我從職業的JavaScript設計模式

function extend (subClass, superClass) { 
    var F = function() {}; 
    F.prototype = superClass.prototype; 
    subClass.prototype = new F(); 
    subClass.prototype.constructor = subClass; 

    subClass.superclass = superClass.prototype; 
    if (superClass.prototype.constructor === Object.prototype.constructor) { 
    superClass.prototype.constructor = superClass; 
    } // end if 
} // end extend() 

function Person (name) { 
    this.name = name; 
} // end Person() 
Person.prototype.getName = function() { 
    return this.name; 
}; // end getName() 

function Author (name, books) { 
    Author.superclass.constructor.call(this, name); 
    this.books = books; 
} // end Author() 

extend(Author, Person); 

Author.prototype.getBooks = function() { 
    return this.books; 
}; // end getBooks() 
Author.prototype.getName = function() { 
    var name = Author.superclass.getName.call(this); 
    return name + " , author of " + this.getBooks(); 
}; // end getName() 

var a = new Author("xxx", "xxx"); 
console.log(a.getName()); // xxx , author of xxx 

複製筆者列出來實現繼承三路:基於類,基於原型和增加基礎。

您可以閱讀代碼,也許讀的書..