その形式で記述されたコード (使用していないnew
、完全にプライベートなデータがある場所) を使用する場合、主な障害はCharacter
、インスタンス間で共有できるものが何もないことです。したがって、 によって生成されたオブジェクトCharacter
を他のオブジェクトのプロトタイプとして使用することはできますが、 1 つ Character
のオブジェクトを作成して、それを複数の派生オブジェクトのプロトタイプとして再利用することはできません。
Villian
それぞれが独自の基本Character
オブジェクトをプロトタイプとして取得するオブジェクトを生成する関数 ( など) を作成する方法は次のとおりです。
function Villian(startX) {
var rv = Object.create(Character(startX));
rv.doEvilThing = function() {
};
return rv;
}
Villian
新しいCharacter
オブジェクトを作成し、それをオブジェクトのプロトタイプとして割り当てVillian
ます。もちろん、これは を呼び出すたびに、 の一部が s間で再利用できるVillian
場合のように 1 つではなく 2 つのオブジェクトが作成されることを意味します。Character
Villian
オブジェクトを直接Villian
拡張することもできます:Character
function Villian(startX) {
var rv = Character(startX);
rv.doEvilThing = function() {
};
return rv;
}
Villian
これはオブジェクトを 1 つだけ作成し、その側面と側面を区別しませんCharacter
。
が必要であり、真にプライベートCharacter
であるためにこのように記述されている場合(ただし、どちらにもセッターとゲッターの両方があるため、その理由はあまりわかりません)、の基礎となるパターンを使用することをお勧めします。 ES6 のプライベート プロパティは、現在使用しているパターンとは異なり、共有プロトタイプ オブジェクトに適しています。x
swipe
新しい ES6 の機能を待たずに、今日それをほぼ実現する方法についての記事を書きました。Name
要約: ES6 は、文字列ではないが、プロパティの名前として使用できる新しい " " オブジェクトを導入します。そのオブジェクトは、プロパティを参照するときに名前の代わりに使用できます。例えば:
var x = new Name(); // Create the private name object
this[x] = value; // Put a property on the object with that name
プライベートName
オブジェクトは不透明であり、既定では、プライベート オブジェクトで作成されたプロパティは列挙できません。
全体のパターンはこちら。(ここではコーディング スタイルに固執しようとしましたが、バリエーションについてはお詫びします。)上記とは異なり、これらCharacter
とを一緒にVillian
使用する必要があることに注意してください。以下に、これを行わずにこれを行う方法を示します(これは小さな変更です)。new
Character
new
var Character = (function() {
var x = new Name(); // The *name* for our `x` property
var swipe = new Name(); // The *name* for our `swipe` property
/* Character class*/
var Character = function(startX) {
this[x] = startX;
this[swipe] = 0;
};
Character.prototype.getX = function() {
return this[x];
};
Character.prototype.getSwipe = function(){
return this[swipe];
};
// ...etc...
return Character;
})();
var Villian = (function() {
/* Villian class*/
var Villian = function(startX) {
Character.call(this, startX);
};
Villian.prototype = Object.create(Character.prototype);
Villian.prototype.doEvilThing = function() {
// ...
};
return Villian;
})();
Name
プロトタイプにさまざまなメソッドがあり、プロパティは実際にはプロパティであることに注意してください (使用しているパターンではそれらはプライベートですが、プロパティではありません)。それらのプロパティを外部のコードで使用することはできません。
ES5 以前 (たとえば、今日) では、ES6 の代わりに機能する必要がありますName
。私の記事で提供するものは、繰り返さないランダムな文字列を使用するだけです:
var Name = function() {
var used = {};
function Name() {
var length, str;
do {
length = 5 + Math.floor(Math.random() * 10);
str = "_";
while (length--) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
}
while (used[str]);
used[str] = true;
return new String(str); // Since this is called via `new`, we have to return an object to override the default
}
return Name;
}();
なしでも同じことができますnew
。変更されるのは実際の関数Character
とVillian
関数だけですが、わかりやすくするためにすべてを含めます。
var Character = (function() {
var x = new Name(); // The *name* for our `x` property
var swipe = new Name(); // The *name* for our `swipe` property
/* Character class without using `new` */
var Character = function(startX) {
var c = Object.create(Character.prototype);
c[x] = startX;
c[swipe] = 0;
return c;
};
Character.prototype.getX = function() {
return this[x];
};
Character.prototype.getSwipe = function(){
return this[swipe];
};
// ...etc...
return Character;
})();
var Villian = (function() {
/* Villian class without using `new` */
var Villian = function(startX) {
var v = Object.create(Villian.prototype);
Character.call(v, startX);
return v;
};
Villian.prototype = Object.create(Character.prototype);
Villian.prototype.doEvilThing = function() {
// ...
};
return Villian;
})();