あらゆるプログラミングはコードの再利用を提案します。そうしないと、新しいプログラムを開発したり、新しい関数を作成したりするたびに新しいプログラムを書かなければなりません。しかし、コードの再利用には良い面と悪い面があります。次の 2 つの記事では、コードの再利用について説明します。最初の記事は、問題が発生する可能性があるため、これらのパターンの使用を避けることを示しています。2 番目の記事は、「これはすべての人に推奨されるモードです」を参照しています。使用するには、通常は問題ありません。
モード 1: デフォルト モード
一般的に使用されるデフォルト モードのコードの再利用は、多くの場合問題になります。このモードでは、Parent() のコンストラクターを使用してオブジェクトが作成され、このオブジェクトが割り当てられます。 Child() のプロトタイプに。コードを見てみましょう:
関数assign(C, P) { C.prototype = new P();}
// 親コンストラクター関数 Parent(name) { this.name = name 'Adam';}
// Say 関数を追加プロトタイプへ Parent.prototype .say = function () { return this.name;}
// 子コンストラクターは空です function Child(name) {}
// 継承を実行します extend(Child, Parent); var kid = new Child ();console.log(kid.say());
// "Adam"var kiddo = new Child();kiddo.name = "Patrick";console.log(kiddo.say) ());
// "Patrick"// 欠点: パラメータを Child コンストラクターに渡すことができません var s = new Child(s.say()); / "Adam" このモードの欠点は、Child がパラメーターを渡すことができないため、基本的には役に立たないことです。
モード 2: コンストラクターの借用
このモードでは、子が親のコンストラクターを適用用に借用し、子の this とパラメーターを適用に渡します。メソッド。:
// 親コンストラクター関数 Parent (name) { this.name = name || 'Adam';}
// Say 関数をプロトタイプに追加します Parent.prototype.say = function () { return this.name;};子コンストラクター関数 Child( name) { Parent.apply(this, argument);}var kid = new Child("Patrick");console.log(kid.name);
// "Patrick"// 欠点:コンストラクターなし Say メソッドを継承します console.log(typeof kid.say); // 「未定義」の欠点も、継承されていないため使用できないことは明らかです。
モード 3: コンストラクターを借用してプロトタイプを設定する
上記 2 つのモードにはそれぞれ欠点があるので、両方の欠点を取り除くにはどうすればよいでしょうか?試してみてください:
// 親コンストラクター function Parent(name) { this.name = name || 'Adam';}// Say 関数をプロトタイプに追加します Parent.prototype.say = function () { return this 。 name;};//子コンストラクター function Child(name) { Parent.apply(this, argument);}Child.prototype = new Parent();var kid = new Child("Patrick");console.log( kid. name); // "パトリック"console.log(typeof kid.say()); // パトリックコンソール.dir(kid); 削除 kid.name;console.log (子供) .say()); // 「Adam」が実行され、すべてが正常ですが、親コンストラクターが 2 回実行されるため、プログラムは使用できますが、効率が非常に低いことに気づきました。 モード 4: 共有プロトタイプ
共有プロトタイプは、子と親が同じプロトタイプを使用することを意味します。 コードは次のとおりです。
コードをコピーします
コードは次のとおりです: function raise(C, P) { C.prototype = P.prototype;}
// 親コンストラクター function Parent (name) { this.name = name || 'Adam';}
// Say 関数をプロトタイプに追加 Parent.prototype.say = function () { return this.name;} ;
// 子の構築 Function function Child(name) {}inherit(Child, Parent);var kid = new Child('Patrick');console.log(kid.name);
// 未定義のコンソール。 log(typeof kid.say);
// functionkid.name = 'Patrick'; console.log(kid.say());
// Patrickconsole.dir(kid); Child のパラメータが正しく受信されませんでした。
モード 5: 一時コンストラクター
最初にコンストラクターを借用し、次に子のプロトタイプを借用したコンストラクターのインスタンスに設定し、最後に子のプロトタイプを復元します。のコンストラクター。コードは次のとおりです:
コードをコピーします
コードは次のとおりです:
/* Closure*/var extend = (function () { var F = function () { }; return function (C, P) { F.prototype = P.prototype; C.prototype = new F (); C.uber = P.prototype; CC.prototype.constructor = C; }} ());function Parent(name) { this.name = name 'Adam';}// プロトタイプに発言を追加しますFunction Parent.prototype.say = function () { return this.name;};// 子コンストラクター function Child(name) {}inherit(Child, Parent);var kid = new Child();console.log(kid . name); // unknownconsole.log(typeof kid.say); // functionkid.name = 'Patrick';console.log(kid.say()); // Patrickvar kid("Tom"); .log(kid.say()); console.log(kid.constructor.name); // Childconsole.log(kid.constructor === Parent); // false 問題は変わらず、Child はパラメータを正常に受信できません。 。
モード 6: klass
このモードでは、次のコードから始めましょう:
var klass = function (Parent, props) { var Child, F, i / /
1. // 新しいコンストラクター Child = function () { if (Child.uber && Child.uber.hasOwnProperty("__construct")) { Child.uber.__construct.apply(this, argument); Child .prototype.hasOwnProperty("__construct")) { Child.prototype.__construct.apply(this, argument) } }; //
2. ParentParent = 関数を継承します。 { }; F.prototype = Parent.prototype; Child.prototype = new F(); ChildChild.prototype.constructor = Child; in props) { if (props.hasOwnProperty(i)) { Child.prototype[i] = props[i] } }
// "クラス" return Child;};var Man = klass(null, { __construct: function (what) { console.log("Man のコンストラクター"); getName: function () { return this.name }});var first = new Man('Adam' ) ;
// "人間のコンストラクター" をログします first.getName();
// "アダム" var SuperMan = klass(Man, { __construct: function (what) { console.log("スーパーマンのコンストラクター") ; }, getName: function () { var name = SuperMan.uber.getName.call(this); return "私は " name; }});var clark = new SuperMan('Clark Kent');clark.getName( ) ;
// 「私はクラーク・ケントです」console.log(clarkinstanceofMan);
//trueconsole.log(clarkinstanceofSuperMan);
ちょっとめまいを感じますが、よく言えば、このパターンの構文と仕様は他の言語と同じです。使用してもよろしいでしょうか。
概要 上記の 6 つのモードは、特定の特殊な状況で特定の機能を実現しますが、それぞれに独自の欠点があるため、一般的には使用を避けるべきです。