[解決済み] Javascriptの継承:スーパーコンストラクタを呼び出すか、プロトタイプチェーンを使用するか?
質問
ごく最近、MDC における JavaScript 呼び出しの使用について読みました。
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
以下に示す例の一つのリンク、私はまだ理解していない。
なぜここで継承を使うのか
Prod_dept.prototype = new Product();
は必要なのでしょうか?の中にスーパーコンストラクタへの呼び出しがあるからです。
Prod_dept()
とにかく、このように
Product.call
は、単に一般的な動作から外れているだけなのでしょうか?スーパーコンストラクタの呼び出しやプロトタイプチェーンの使用はいつが良いのでしょうか?
function Product(name, value){
this.name = name;
if(value >= 1000)
this.value = 999;
else
this.value = value;
}
function Prod_dept(name, value, dept){
this.dept = dept;
Product.call(this, name, value);
}
Prod_dept.prototype = new Product();
// since 5 is less than 1000, value is set
cheese = new Prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
car = new Prod_dept("honda", 5000, "auto");
わかりやすい説明ありがとうございます。
どのように解決するのですか?
本当の質問の答えは、両方を行う必要があるということです。
- prototype を親のインスタンスに設定すると、prototype チェーン (継承) が初期化され、これは一度だけ行われます (prototype オブジェクトが共有されるため)。
- 親のコンストラクタを呼び出すと、オブジェクト自体が初期化されます。これはインスタンス化のたびに行われます(コンストラクタのたびに異なるパラメータを渡すことができます)。
したがって、継承を設定する際には、親のコンストラクタを呼び出してはいけません。他のオブジェクトを継承するオブジェクトをインスタンス化するときだけです。
Chris Morganの回答はほぼ完璧ですが、細かい点(コンストラクタのプロパティ)が抜けています。継承を設定するための方法を提案させてください。
function extend(base, sub) {
// Avoid instantiating the base class just to setup inheritance
// Also, do a recursive merge of two prototypes, so we don't overwrite
// the existing prototype, but still maintain the inheritance chain
// Thanks to @ccnokes
var origProto = sub.prototype;
sub.prototype = Object.create(base.prototype);
for (var key in origProto) {
sub.prototype[key] = origProto[key];
}
// The constructor property was set wrong, let's fix it
Object.defineProperty(sub.prototype, 'constructor', {
enumerable: false,
value: sub
});
}
// Let's try this
function Animal(name) {
this.name = name;
}
Animal.prototype = {
sayMyName: function() {
console.log(this.getWordsToSay() + " " + this.name);
},
getWordsToSay: function() {
// Abstract
}
}
function Dog(name) {
// Call the parent's constructor
Animal.call(this, name);
}
Dog.prototype = {
getWordsToSay: function(){
return "Ruff Ruff";
}
}
// Setup the prototype chain the right way
extend(Animal, Dog);
// Here is where the Dog (and Animal) constructors are called
var dog = new Dog("Lassie");
dog.sayMyName(); // Outputs Ruff Ruff Lassie
console.log(dog instanceof Animal); // true
console.log(dog.constructor); // Dog
クラスを作成する際のさらなる構文上の工夫については、私のブログ記事を参照してください。 http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
Ext-JSからコピーしたテクニックと http://www.uselesspickles.com/class_library/ からのコメントと https://stackoverflow.com/users/1397311/ccnokes
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで二重引用符と単一引用符はいつ使うべきですか?
-
[解決済み] JavaScriptでsetIntervalの呼び出しを停止する
-
[解決済み] JavaScriptにおける__proto__ VS. prototype
-
[解決済み] Javascriptのcall() & apply() vs bind()?
-
[解決済み] JavaScript で範囲を作成する - 奇妙な構文
-
[解決済み] javascript の関数から `undefined` と `null` のどちらを返すのが良いのでしょうか?
-
[解決済み] Reactコンポーネントでthis.setStateを複数回使用するとどうなりますか?
-
[解決済み] JavaScriptでの大文字小文字を区別しない正規表現
-
[解決済み] Javascriptで動的に命名されたメソッドを呼び出すにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JavaScript で範囲を作成する - 奇妙な構文
-
[解決済み] <Enter>でjQuery UIダイアログを送信する
-
[解決済み] 文字列がすべて同じ部分文字列で構成されているかどうかを調べるにはどうすればよいですか?
-
[解決済み] Chart.jsを使ってドーナツチャートの中にテキストを追加するには?
-
[解決済み] JavaScriptで、ある文字列が別の文字列の中に出現するすべてのインデックスを見つけるにはどうすればよいですか?
-
[解決済み] Chromeの拡張機能開発にWebStormを使用するにはどうすればよいですか?
-
[解決済み] Promise : then vs then + catch [重複].
-
[解決済み] 文字列とラベルのローカライズとグローバリゼーションのベストプラクティス【終了しました
-
[解決済み] Node.jsのES6クラスをrequireで作る
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?