私はこの質問に答えようとします:
オブジェクトを正しい方法で作成していますか? 私が基本的に達成したいのは、コンストラクターを取り除くことです。
最初の小さな例。この単純な構造があると想像してください。
var Slideshow = function(type) {
this.type = type;
}
Slideshow.prototype.nextSlide = function() {
console.log('next slide');
}
Slideshow.prototype.deleteSlideshow = function() {
console.log('delete slideshow');
}
var AdvancedSlideshow = function(bgColor) {
this.bgColor = bgColor;
}
AdvancedSlideshow.prototype.showMeBgColor = function() {
console.log('bgColor iS: ' + bgColor);
}
AdvancedSlideshow
から継承したいと思いSlideshow
ます。したがって、親のすべての関数をその子のインスタンスで使用できるようにする必要があります。私Object.create
たちがそれをしなかった場合:
// THIS CODE ISNT CORRECT
// code for slideshow is same
var AdvancedSlideshow = function(type, bgColor) {
// this line can supply whole Slideshow constructor
Slideshow.call( this, type );
this.bgColor = bgColor;
}
AdvancedSlideshow.prototype = Slideshow.prototype; // there problems start!!!!
AdvancedSlideshow.prototype.showMeBgColor = function() { // we did augumentation of Slideshow
console.log('bgColor is: ' + bgColor);
}
AdvancedSlideshow
は からすべてを継承するようになりましSlideshow
たが、からもSlideshow
すべてを継承しAdvancedSlideshow
ます。それは私たちが望んでいないことです。
var simpleSlideshow = new Slideshow('simple');
simpleSlideshow.showMeBgColor(); // ReferenceError: bgColor is not defined
// but function exists and that's wrong!
そのため、より複雑なものを使用する必要があります。Douglas Crockford が昔作ったポリフィルがあります。
if (!Object.create) {
Object.create = function (o) {
if (arguments.length > 1) {
throw new Error('Object.create implementation only accepts the first parameter.');
}
function F() {}
F.prototype = o;
return new F();
};
}
最初はポリフィルではなく、小さなパターンで、それ以外のように見えました。しかし、パターンは進化していて、JavaScript の一部になったのはとても良いことでした。これで、ecmascript-5 をサポートしないブラウザ用のポリフィルができました。そして、次のようにコーディングできます。
// THIS IS CORRECT
AdvancedSlideshow.prototype = Object.create(Slideshow.prototype);
それ以外の
function F() {};
F.prototype = Slideshow.prototype;
AdvancedSlideshow.prototype = new F();
次にAdvancedSlideshow
から継承しますSlideshow
が、から継承Slideshow
しませんAdvancedSlideshow
。
したがって、の目的はObject.create
、コンストラクターや「新しい」キーワードを取り除くことではありません。その目的は、正しいプロトタイプ チェーンを作成することです。
EDIT 20.2.2014:
数日前、そのconstructor
プロパティがプロトタイプ チェーンの一部であることに気付きました。したがってObject.create
、継承に使用する場合はconstructor
、子オブジェクトのプロパティ (コンストラクター自体ではなく、単なるプロパティ) も変更します。したがって、子オブジェクトの新しいインスタンスのコンストラクタ プロパティは、その親を指します。これは simple で修正できますChild.prototype.constructor = Child
。
...
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var first = new Child();
first.constructor === Child; // true
first.constructor === Parent; // false
first instanceOf Child; // true
first instanceOf Parent; // true
現在、Object.create には 2 番目のパラメーターがあり、オブジェクトの「隠された秘密」を伝えることができます。ただし、必要がないため、これを行うことはお勧めしません。いくつかのパターンのようにも機能する高度なものです。
コンストラクター、「new」キーワード、または重要なものを避けたい場合は、おそらくファクトリーパターンを探しているでしょう。ただし、覚えておいてください。たとえば、"new" にはいくつかの弱点がありますが、組み込み機能を削除するパターンは通常より悪いです! とにかく、ここでインスピレーションを見つけることができるかもしれません。
http://www.2ality.com/2010/12/javascripts-prototypal-inheritance.html