オブジェクトの作成、継承のための完璧な方法
4372 ワード
最近は「JavaScript高級プログラム設計」を採用しています.JavaScriptを書くのは長くなりましたが、まだ新しいものを習っています.順番に見ないで、役に立つものを見たらメモを取ります.
1.オブジェクトを作成する方法
本の中で7種類の実用化の対象の方式を持っていますが、どれもよく使われていて、完璧なのは「組み合わせモード」と「動態原形モード」です.
グループモード:
私がずっと使っていたのは「コンビネーションモード」でした.
ダイナミック原形パターン:
本では上のコードの第二の文を構造関数
2.継承
正統派の対象言語に対して、JavaScriptは「継承の実現」のみをサポートしていますが、「継承の実現」には6つの方法があります.見れば見るほど、JSの水深が感じられます.ほとんどの方法は完璧ではありません.その中で、「組み合わせ継承」と「寄生結合式継承」は相対的に完璧です.しかし、この2つの方法は他の完璧ではない補完的な組み合わせの上にあります.完璧ではない方式を飛び越えて、直接に干物に行きます.今度振り返った時にまたこの6つの方式を見直すのは嫌です.
グループ引継ぎ
寄生ユニット引き継ぎ
上記の方法は既によく使われていますが、「寄生結合式継承」は主に複数の属性を除去するためです.
この文章はノートを学ぶので、私がある知識点を勉強する時の理解と総括で、自分で復習しやすい同時に必要な人にも助けてほしいです.
1.オブジェクトを作成する方法
本の中で7種類の実用化の対象の方式を持っていますが、どれもよく使われていて、完璧なのは「組み合わせモード」と「動態原形モード」です.
グループモード:
私がずっと使っていたのは「コンビネーションモード」でした.
function F(a, b) {
this.a = a;
this.b = b;
}
F.prototype.getAB = function() {
console.log(this.a, this.b);
}
大きな問題はないですが、二つの部分に分けられていて、パッケージ性が欠けています.位置を変えるのはよくないです.ダイナミック原形パターン:
本では上のコードの第二の文を構造関数
F()
内に置いています.function F(a, b) {
this.a = a;
this.b = b;
F.prototype.getAB = function() {
console.log(this.a, this.b);
}
}
これは「テイクアウト」ですが、new F()
を呼び出すたびに、F.prototype
に属性をリセットします.F.prototype
は最初の設定だけでいいです.//
function F(a, b) {
this.a = a;
this.b = b;
if (typeof this.getAB != "function") { // ,
F.prototype.getAB = function() {
console.log(this.a, this.b);
}
}
}
コンストラクタの原形オブジェクトF.prototype
に複数の方法がある場合、複数のif
文を用いて個別に判断する必要はなく、その中の一つがすなわちF.prototype
が初期化されたことを示すだけであると判断する必要がある.2.継承
正統派の対象言語に対して、JavaScriptは「継承の実現」のみをサポートしていますが、「継承の実現」には6つの方法があります.見れば見るほど、JSの水深が感じられます.ほとんどの方法は完璧ではありません.その中で、「組み合わせ継承」と「寄生結合式継承」は相対的に完璧です.しかし、この2つの方法は他の完璧ではない補完的な組み合わせの上にあります.完璧ではない方式を飛び越えて、直接に干物に行きます.今度振り返った時にまたこの6つの方式を見直すのは嫌です.
グループ引継ぎ
//
//
function SuperType(a, b) {
this.a = a;
this.b = b;
}
SuperType.prototype.getAB = function() {
console.log(this.a, this.b);
}
//
function SubType(a, b, c) {
SuperType.apply(this, [a, b]); //
this.c = c;
}
SubType.prototype = new SuperType(); // ( )
SubType.prototype.constructor = SubType; // constructor
//
var sub = new SubType(1, 2, 3); // SubType, sub : Object { a: 1, b: 2, c: 3 }
Object.getPrototypeOf(sub); // sub :Object { a: undefined, b: undefined }
上記のコードは、超クラスSuperTypeを定義しており、a
、b
の2つの例示的な属性と、超クラスの原形に位置するgetAB()
の方法とを備えています.SubTypeは、スーパークラスのすべての属性を継承する必要があります.したがって、SuperType()
関数において、call()
またはapply()
を使用して、thisがサブクラスを指すようにする.すなわち、スーパークラスの構造関数を借りてサブクラスを作成するための例示的な属性である.SubType.prototype = new SuperType();
は超種類の正体を確保する方法も布団類に引き継がれます.しかし、上記のコードObject.getPrototypeOf(sub);
は、上記のような例sub
の原形を見たときには、getAB()
の方法が見られませんでした.sub
は、getAB()
の方法を継承していますか?実際には継承があるが、getAB()
方法をsub
の原形に直接置かず、sub
の「原形」に置くだけで、Object.getPrototypeOf(Object.getPrototypeOf(sub))
を実行してgetAB()
方法を含むオブジェクトを得ることができる.上記の継承方法は、instanceof
およびisPrototypeOf()
のいずれも、継承対象を正常に識別することができる.比較的完璧な方法であるが、上記のコードブロックの最後の文の注釈に留意して、sub
の原形には訪問されないa
、b
属性が現れている.これらの無駄なものはこの方法に最適な空間があることを証明しています.寄生ユニット引き継ぎ
上記の方法は既によく使われていますが、「寄生結合式継承」は主に複数の属性を除去するためです.
//
//
function SuperType(a, b) {
this.a = a;
this.b = b;
}
SuperType.prototype.getAB = function() {
console.log(this.a, this.b);
}
//
function SubType(a, b, c) {
SuperType.apply(this, [a, b]); //
this.c = c;
}
// , ,
SubType.prototype = Object.create(SuperType.prototype); // 。
SubType.prototype.constructor = SubType; // constructor
//
var sub = new SubType(1, 2, 3); // SubType, sub : Object { a: 1, b: 2, c: 3 }
Object.getPrototypeOf(sub); // sub :Object { constructor: SubType() }
Object.getPrototypeOf(Object.getPrototypeOf(sub)); //Object { getAB: SuperType.prototype.getAB() , constructor: SuperType() }
上の継承方式は元の属性を継承する時にコードが違っています.undefined
方法を使って新しいオブジェクトを作成しました.このオブジェクトの原形はまさに超種類の原形です.そしてこの新しいオブジェクトをサブクラスの原形に形成します.したがって、サブクラスの原形は超種類の原形だけを含んでおり、もはやスーパークラスのインスタンスにおける属性または方法を含んでいない.「2つの属性」の浪費を回避し、両方の美しさとも言える.同様に、スーパークラスの方法Object.create()
は、このような「原形」の中にある.この方法の改造は超種の正体などを原形にしたものである以上、そのままgetAB()
でいいのではないでしょうか?もちろんいけません.対象は引用タイプです.このように原形に添加すると超種の原形が汚染されますので、上と似た方法で超種の原形の副本をサブタイプの原形に付与します.同様にSubType.prototype = SuperType.prototype
およびinstanceof
は、継承対象を正常に識別することができ、完璧である.この文章はノートを学ぶので、私がある知識点を勉強する時の理解と総括で、自分で復習しやすい同時に必要な人にも助けてほしいです.