一.プロトタイプパターン
既存のオブジェクトをプロトタイプとして、clone を通じて新しいオブジェクトを取得する(新しいオブジェクトの作成プロセスを簡素化するため)
([黯羽軽揚:デザインパターンまとめ(《Head First デザインパターン》学習まとめ)](/articles/デザインパターンまとめ(《head-first デザインパターン》学習まとめ)/) から引用)
継承と非常に似ており、プロトタイプパターンをさらに強化すると継承になります。プロトタイプパターンは属性のコピーのみを気にし、継承は属性のコピーを実現する他に親/子タイプの階層関係を保証する必要があります
二.具体的な実装
###1.基本原理
// 生孩子函数
function beget(obj) {
var F = function() {};
F.prototype = obj;
return new F();
}
// test
var obj = {
attr: 1,
fun: function() {
console.log(this.attr);
}
}
var cp_obj = beget(obj);
cp_obj.fun(); // 1
核心は beget 関数で、渡されたオブジェクトを空のコンストラクタのプロトタイプに入れ、オブジェクトを作成して返すだけです
明らかな欠点があります:プロトタイプオブジェクト(この例では obj)からの属性がうっかり上書きされる可能性があります
P.S.プロトタイプオブジェクト obj はどのような方法で作成されたオブジェクトでもよく、この例ではオブジェクトリテラルですが、もちろん new で作成されたものでも、beget で作成されたものでも構いません
###2.簡単な強化
ES5 は Object.create 関数をサポートしており、浅いコピーのオブジェクトを取得できます。beget を直接以下に置き換えられます:
Object.create(obj);
結果は全く同じです。Object.create の内部実装はダグラスのプロトタイプパターンからインスピレーションを受けているためです。さらに Object.create には 2 番目のパラメータがあり、属性を定義するために使用できます:
Object.create(obj, {
attr: {
value: 2,
writable: false, // デフォルト値
configurable: false, // デフォルト値
enumerable: true
}
});
実際には Object.create と Object.defineProperty を一緒にしたもので、例えば:
// test
var obj = {
attr: 1,
fun: function() {
console.log(this.attr);
}
}
var cp_obj = Object.create(obj, {
attr2: {
value: 2,
writable: false, // デフォルト値
configurable: false, // デフォルト値
enumerable: true
}
});
cp_obj.fun(); // 1
console.log(cp_obj.attr2); // 2
cp_obj.attr2 = 3;
console.log(cp_obj.attr2); // 2、書き込み不可
もちろん、Object.defineProperty も ES5 でサポートされているため、配合して使用することは一種の強化(アクセス制御)と言えます
三.プロトタイプパターンの利点
本に素晴らしい言葉があります:
Prototype パターンを使用する利点の 1 つは、JavaScript 自体が持つプロトタイプの優位性を獲得できることであり、他の言語の特性を模倣しようとするのではありません。
Java で実装されたプロトタイプパターンは奇妙に見えます。プロトタイプパターン自体而言、Java 中の Object.clone で需要を満たせるからです。他のどのような形式の実装も余計に見えます。一方、JavaScript は当初 clone のネイティブ実装を提供していませんでした(ES5 の Object.create がこの欠陥を補いました)。そのためプロトタイプパターンが必要でしたが、ES5 が生産に投入された後は手動でプロトタイプパターンを実装する必要はなくなりました
プロトタイプパターンに関するさらに多くの紹介は 23 種デザインパターン(5):プロトタイプパターン を参照
参考資料
-
《JavaScript デザインパターン》
コメントはまだありません