その形式で記述されたコード (使用していない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 つのオブジェクトが作成されることを意味します。CharacterVillian
オブジェクトを直接Villian拡張することもできます:Character
function Villian(startX) {
var rv = Character(startX);
rv.doEvilThing = function() {
};
return rv;
}
Villianこれはオブジェクトを 1 つだけ作成し、その側面と側面を区別しませんCharacter。
が必要であり、真にプライベートCharacterであるためにこのように記述されている場合(ただし、どちらにもセッターとゲッターの両方があるため、その理由はあまりわかりません)、の基礎となるパターンを使用することをお勧めします。 ES6 のプライベート プロパティは、現在使用しているパターンとは異なり、共有プロトタイプ オブジェクトに適しています。xswipe
新しい 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使用する必要があることに注意してください。以下に、これを行わずにこれを行う方法を示します(これは小さな変更です)。newCharacternew
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;
})();