違いは何ですか
var A = function () {
this.x = function () {
//do something
};
};
そして
var A = function () { };
A.prototype.x = function () {
//do something
};
例は非常に異なる結果をもたらします。
違いを見る前に、次の点に注意してください。
[[Prototype]]
プロパティを介してインスタンス間でメソッドと値を共有する方法を提供します。myObj.method()
)、メソッド内のthisはそのオブジェクトを参照します。thisが呼び出しによってもbindの使用によっても設定されていない場合は、グローバルオブジェクト(ブラウザのウィンドウ)または厳密モードにデフォルト設定されます。未定義のままです。問題のスニペットは次のとおりです。
var A = function () {
this.x = function () {
//do something
};
};
この場合、変数A
には関数への参照である値が割り当てられます。その関数がA()
を使用して呼び出されると、その関数のthisはグローバルオブジェクトに設定されないため、式this.x
は有効なwindow.x
です。その結果、右側の関数式への参照がwindow.x
に割り当てられます。
の場合:
var A = function () { };
A.prototype.x = function () {
//do something
};
非常に異なる何かが起こります。最初の行で、変数A
に関数への参照が割り当てられています。 JavaScriptでは、すべての関数オブジェクトにデフォルトでprototypeプロパティがあるため、A.prototypeオブジェクトを作成するためのコードは別にありません。
2行目のA.prototype.xに、関数への参照が割り当てられています。存在しない場合はxプロパティを作成し、存在する場合は新しい値を割り当てます。そのため、オブジェクトのxプロパティが式に含まれている最初の例との違いがわかります。
別の例は以下の通りです。それは最初のものに似ています(そしておそらくあなたが尋ねようとしていたもの):
var A = new function () {
this.x = function () {
//do something
};
};
この例では、new
演算子が関数式の前に追加されているため、関数はコンストラクタとして呼び出されます。 new
で呼び出されると、関数のthisは、プライベートの[[Prototype]]
プロパティがコンストラクタのpublicprototypeを参照するように設定されている新しいObjectを参照するように設定されます。そのため、代入文では、この新しいオブジェクトにx
プロパティが作成されます。コンストラクタとして呼び出されると、関数はデフォルトでそのthisオブジェクトを返すので、別のreturn this;
ステートメントは必要ありません。
Aにxプロパティがあることを確認するには、次のようにします。
console.log(A.x) // function () {
// //do something
// };
コンストラクタを参照する唯一の方法はA.constructorであるため、これはnewの珍しい使い方です。もっと一般的なことです:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
同様の結果を得るためのもう1つの方法は、すぐに呼び出される関数式を使用することです。
var A = (function () {
this.x = function () {
//do something
};
}());
この場合、A
は右側の関数呼び出しの戻り値を代入しています。ここでも、thisは呼び出しで設定されていないため、グローバルオブジェクトを参照し、this.x
は有効なwindow.x
です。関数は何も返さないので、A
はundefined
の値を持ちます。
この2つのアプローチの違いは、JavaScriptオブジェクトをJSONとの間でシリアライズおよびデシリアライズする場合にも明らかになります。オブジェクトのプロトタイプで定義されたメソッドは、オブジェクトをシリアル化してもシリアル化されません。たとえば、オブジェクトのデータ部分だけをシリアル化したい場合に便利ですが、そのメソッドではありません。
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
関連する質問:
サイドノート:2つの方法の間でメモリ使用量を大幅に節約することはできませんが、メソッドとプロパティを共有するためにプロトタイプを使用すると、各インスタンスよりメモリ使用量が少なくなります。独自のコピーを持っています。
JavaScriptは低レベルの言語ではありません。プロトタイピングや他の継承パターンを、メモリの割り当て方法を明示的に変更する方法として考えることは、あまり意味がありません。
他の人が最初のバージョンを言ったように、 "this"を使用すると、クラスAのすべてのインスタンスが関数メソッド "x"の独自の独立したコピーを持つことになります。 "prototype"を使用することは、クラスAの各インスタンスがメソッド "x"の同じコピーを使用することを意味します。
この微妙な違いを示すためのコードをいくつか示します。
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
他の人が述べたように、どちらかの方法を選択するにはさまざまな理由があります。私のサンプルは、その違いを明確に示すためのものです。
次の2つの例を見てください。
var A = function() { this.hey = function() { alert('from A') } };
vs.
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
ここのほとんどの人々(特にトップ評価の回答)は、なぜ説明することなく、彼らがどのように異なるかを説明しようとしました。これは間違っていると思います。最初に基本を理解すると、違いが明らかになります。最初に基礎を説明してみましょう...
a)関数はJavaScriptのオブジェクトです。 JavaScriptのすべてのオブジェクトは内部プロパティを取得します(つまり、Chromeのようなブラウザを除き、他のプロパティのようにアクセスすることはできません)。しばしば__proto__
(実際にはanyObject.__proto__
と入力できますChromeそれが参照するものを見るために、これはただのプロパティ、それ以上、JavaScriptのプロパティ=オブジェクト内の変数、それ以上ではありません。
では、この__proto__
プロパティは何を指しているのでしょうか?まあ、通常は別のオブジェクト(理由については後で説明します)。 __proto__
プロパティのJavaScriptが別のオブジェクトをポイントしないように強制する唯一の方法は、var newObj = Object.create(null)
を使用することです。これを行っても、__proto__
プロパティはオブジェクトのプロパティとして存在しますが、別のオブジェクトを指さないだけで、null
を指しています。
ほとんどの人が混乱する場所は次のとおりです。
JavaScriptで新しい関数を作成すると(オブジェクトでもありますが、覚えていますか?)、定義されるとすぐに、JavaScriptはprototype
という関数に新しいプロパティを自動的に作成します。それを試してみてください:
var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined
A.prototype
は、__proto__
プロパティとは完全に異なります。この例では、「A」には「prototype」および__proto__
という2つのプロパティがあります。これは人々にとって大きな混乱です。 prototype
および__proto__
プロパティはまったく関係がなく、別々の値を指す別々のものです。
あなたは不思議に思うかもしれません:なぜJavaScriptにはすべてのオブジェクトに__proto__
プロパティが作成されているのですか? 1つの単語:delegation。オブジェクトのプロパティを呼び出したときに、そのオブジェクトにオブジェクトがない場合、JavaScriptは__proto__
によって参照されるオブジェクトを探して、おそらくそれを持っているかどうかを確認します。持っていない場合、チェーンが終了するまで、そのオブジェクトの__proto__
プロパティなどを調べます。したがって、名前プロトタイプチェーン。もちろん、__proto__
がオブジェクトをポイントせず、代わりにnull
をポイントしている場合、幸運なことに、JavaScriptはそれを認識し、プロパティのundefined
を返します。
また、関数を定義するときに、JavaScriptが関数のprototype
というプロパティを作成するのはなぜだろうと思うかもしれません。それはあなたをだまそうとするので、はいあなたをだますクラスベースの言語のように動作すること.
例に進み、A
から「オブジェクト」を作成しましょう。
var a1 = new A();
このことが起こったとき、バックグラウンドで何かが起こっています。 a1
は、新しい空のオブジェクトが割り当てられた通常の変数です。
関数呼び出しA()
の前に演算子new
を使用したという事実は、バックグラウンドで追加の処理を行いました。 new
キーワードにより、a1
を参照する新しいオブジェクトが作成されましたが、そのオブジェクトは空です。さらに、次のことが発生します。
各関数定義には、prototype
(__proto__
プロパティとは異なり、アクセスできる)と呼ばれる新しいプロパティが作成されると言いました。さて、そのプロパティは現在使用されています。
これで、焼きたての空のa1
オブジェクトができました。 JavaScriptのすべてのオブジェクトには、nullであろうと別のオブジェクトであろうと、何かを指す内部__proto__
プロパティがあります(a1
にもあります)。 new
演算子は、その__proto__
プロパティを設定して、関数のprototype
プロパティを指すようにします。もう一度読んでください。基本的にこれです:
a1.__proto__ = A.prototype;
A.prototype
は空のオブジェクトにすぎないと言いました(a1
を定義する前に別のオブジェクトに変更しない限り)。そのため、基本的にa1.__proto__
は同じものを指しますA.prototype
が指すものは、その空のオブジェクトです。これらは両方とも、この行が発生したときに作成された同じオブジェクトを指します。
A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}
var a1 = new A()
ステートメントが処理されると、別のことが起こります。基本的にA()
が実行され、Aが次のような場合:
var A = function() { this.hey = function() { alert('from A') } };
function() { }
内のすべてのものが実行されます。 this.hey..
行に到達すると、this
がa1
に変更され、次のようになります。
a1.hey = function() { alert('from A') }
this
がa1
に変更される理由については説明しませんが、詳細については これは素晴らしい答えです です。
要約すると、var a1 = new A()
を実行すると、バックグラウンドで3つのことが発生します。
a1
に割り当てられます。 a1 = {}
a1.__proto__
プロパティは、A.prototype
が指す(別の空のオブジェクト{})と同じものを指すように割り当てられます
関数A()
は、ステップ1で作成された新しい空のオブジェクトにthis
を設定して実行されます(this
がa1
に変わる理由について上記で参照した回答を読んでください)
次に、別のオブジェクトを作成してみましょう。
var a2 = new A();
手順1、2、3が繰り返されます。何か気づきましたか?キーワードはrepeat。ステップ1:a2
は新しい空のオブジェクト、ステップ2:その__proto__
プロパティは同じことを指しますA.prototype
が指し、最も重要なのは、ステップ3:関数A()
が再び実行されることです。つまり、a2
は関数を含むhey
プロパティを取得します。 a1
およびa2
には、hey
という名前の2つのSEPARATEプロパティがあり、2つのSEPARATE関数を指します。同じことをしている同じ2つの異なるオブジェクトに重複した関数があります...おっと... new A
で作成された1000個のオブジェクトがある場合、すべての関数宣言が何かよりも多くのメモリを消費した後、これのメモリの意味を想像できます番号2です。これをどのように防ぐのでしょうか。
__proto__
プロパティがすべてのオブジェクトに存在する理由を覚えていますか? a1
(存在しない)でyoMan
プロパティを取得する場合、その__proto__
プロパティが参照され、オブジェクトである場合(そしてほとんどの場合そうです) 、yoMan
が含まれているかどうかをチェックし、含まれていない場合は、そのオブジェクトの__proto__
などを調べます。含まれている場合、そのプロパティ値を取得して表示します。
そのため、誰かがこの事実+ a1
を作成するときに、その__proto__
プロパティが同じ(空の)オブジェクトA.prototype
を指し、これを行うという事実を使用することにしました。
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
クール!これで、a1
を作成すると、上記の3つのステップがすべて実行されます。ステップ3では、function A()
には実行するものがないため、何もしません。そして、私たちがするなら:
a1.hey
a1
にhey
が含まれていないことがわかり、その__proto__
プロパティオブジェクトが存在するかどうかを確認します。
このアプローチでは、新しいオブジェクトが作成されるたびに機能が複製されるステップ3の部分を削除します。 a1
とa2
が個別のhey
プロパティを持っている代わりに、それらのどれも持っていません。今、あなたは自分自身を理解していると思います。それは素晴らしいことです...__proto__
とFunction.prototype
を理解すれば、これらのような質問はかなり明白になります。
注:一部の人々は、内部プロトタイププロパティを__proto__
として呼び出さない傾向があります。この名前を投稿で使用して、2つの異なるものとしてFunctional.prototype
プロパティと明確に区別しています。
ほとんどの場合、それらは基本的に同じですが、2番目のバージョンでは、オブジェクトごとに個別の関数ではなく関数のインスタンスが1つしかないため、メモリを節約できます。
最初の形式を使用する理由は「非公開メンバー」にアクセスするためです。例えば:
var A = function () {
var private_var = ...;
this.x = function () {
return private_var;
};
this.setX = function (new_x) {
private_var = new_x;
};
};
Javascriptのスコープ規則のため、private_varはthis.xに割り当てられた関数で利用できますが、オブジェクトの外側では利用できません。
最初の例では、そのオブジェクトのインターフェースのみを変更しています。 2番目の例は、そのクラスのすべてのオブジェクトのインターフェースを変更します。
this
の代わりにprototype
を使用することによる最終的な問題は、メソッドをオーバーライドするときに、基本クラスのコンストラクターがオーバーライドされたメソッドを参照することです。このことを考慮:
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
対:
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
これが問題ではないと考えるなら、それはあなたがプライベート変数なしで生きることができるかどうか、そしてあなたがそれを見たときにあなたがリークを知るのに十分経験しているかどうかにかかっている。また、メソッド定義の後にコンストラクタロジックを配置しなければならないのは不便です。
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
対:
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
すべてのオブジェクトはプロトタイプオブジェクトにリンクされています。存在しないプロパティにアクセスしようとすると、JavaScriptはそのプロパティのオブジェクトのプロトタイプオブジェクトを調べ、存在する場合はそれを返します。
関数コンストラクターのprototype
プロパティは、new
を使用するときにその関数で作成されたすべてのインスタンスのプロトタイプオブジェクトを参照します。
最初の例では、x
関数で作成された各インスタンスにプロパティA
を追加します。
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
2番目の例では、A
で作成されたすべてのインスタンスが指すプロトタイプオブジェクトにプロパティを追加しています。
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor
結論として、最初の例では関数のコピーが各インスタンスに割り当てられています。 2番目の例では、関数の単一コピーがすべてのインスタンスで共有されています。
違いは何ですか? =>たくさん。
this
バージョンはカプセル化、つまりデータ隠蔽を可能にするために使用されると思います。プライベート変数を操作するのに役立ちます。
次の例を見てみましょう。
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some Housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
これで、prototype
構造体は次のように適用できます。
異なる成人は異なる年齢を持っていますが、すべての成人が同じ権利を取得しています。
だから、これではなくプロトタイプを使って追加します。
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
今実装を見てみましょう。
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
お役に立てれば。
プロトタイプはクラスのテンプレートです。これは将来のすべてのインスタンスに適用されます。これはオブジェクトの特定のインスタンスです。
私がJavaScriptトレーニングコース中に学んだより包括的な答えをあなたにあげましょう。
ほとんどの回答はすでに違いを述べています。つまり、プロトタイプを作成するときにすべての(将来の)インスタンスで共有されています。これに対して、クラスで関数を宣言すると、インスタンスごとにコピーが作成されます。
一般的には、正しいことも悪いこともありません。それは、好みに応じて、または要件に応じて設計を決定することです。プロトタイプは、この回答の最後にあると思いますが、オブジェクト指向の方法で開発するために使用される手法です。
あなたはあなたの質問に2つのパターンを示しました。もう2つ説明し、違いがあれば説明します。自由に編集/拡張してください。すべての例で、それは場所を持ちそして動くことができる車のオブジェクトについてです。
このパターンが今日でもまだ適切であるかどうかわからないが、それは存在する。そしてそれについて知るのは良いことです。オブジェクトとプロパティをdecorator関数に渡すだけです。デコレータはプロパティとメソッドを持つオブジェクトを返します。
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
JavaScriptの関数は特殊なオブジェクトです。呼び出されることに加えて、関数は他のオブジェクトのようにプロパティを格納することができます。
この場合Car
は関数(も think オブジェクト)であり、慣れ親しんだ方法で呼び出すことができます。それはプロパティmethods
(これはmove
関数を持つオブジェクトです)を持ちます。 Car
が呼び出されると、extend
関数が呼び出されます。これは何らかの魔法をかけ、Car
内で定義されたメソッドでmethods
関数(thinkオブジェクト)を拡張します。
この例は異なりますが、質問の最初の例に最も近いものです。
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
最初の2つのパターンは、共有メソッドを定義するための技法の使用、またはコンストラクターの本体内でインラインで定義されているメソッドの使用についての説明を可能にします。どちらの場合も、すべてのインスタンスに独自のmove
関数があります。
プロトタイプの委任による機能共有がプロトタイプのパターンにとってまさに目標であるため、プロトタイプのパターンは同じ検査には向いていません。他の人が指摘したように、それはより良いメモリフットプリントを持つことが期待されています。
ただし、知っておくと便利な点が1つあります。すべてのprototype
オブジェクトには、便利なプロパティconstructor
があります。これは、付属の関数(thinkオブジェクト)を指しています。
最後の3行について
この例では、Car
はprototype
オブジェクトにリンクしています。このオブジェクトはconstructor
を介してCar
自体にリンクしています。つまり、Car.prototype.constructor
はCar
自体です。これにより、どのコンストラクタ関数が特定のオブジェクトを構築したのかを把握できます。
amy.constructor
の検索は失敗するため、コンストラクタープロパティを持つCar.prototype
に委任されます。そしてamy.constructor
はCar
です。
さらに、amy
はinstanceof
Car
です。 instanceof
演算子は、右側のオペランドのプロトタイプオブジェクト(Car
)が、左側のオペランドのプロトタイプ(amy
)チェーンのどこかにあるかどうかを調べることによって機能します。
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
何人かの開発者は最初は混乱するかもしれません。下記の例を参照してください。
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
instanceof
プロトタイプチェーンのどこにもfalse
のプロトタイプが見つからないため、Dog
演算子はfido
を返します。 fido
は、オブジェクトリテラルを使用して作成された単純なオブジェクトです。つまり、単にObject.prototype
に委任します。
これは実際にはプロトタイプ・パターンのもう1つの形式であり、単純化された形式であり、例えばJavaでプログラムを作成する人にとってはなじみのあるものです。これはnew
コンストラクターを使用するためです。
それは実際に原型パターンと同じことをします、それは原型パターンの単なる構文上の糖です。
ただし、主な違いは、擬似古典的パターンを使用する場合にのみ適用されるJavaScriptエンジンで実装された最適化があることです。疑似古典的パターンは原型パターンのおそらくより速いバージョンと考えてください。両方の例のオブジェクトの関係は同じです。
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
最後に、オブジェクト指向プログラミングをどのように行うことができるかを理解することはそれほど難しくないはずです。 2つのセクションがあります。
プロトタイプ(チェーン)内の共通のプロパティ/メソッドを定義する1つのセクション。
そして、オブジェクトを互いに区別する定義を入れる別のセクション(例の中のloc
変数)。
これが、スーパークラスやサブクラスのような概念をJavaScriptに適用することを可能にするものです。
追加または編集してください。もう一度完成すれば、これをコミュニティWikiにすることができます。
@ Matthew Crumleyは正しいと思います。それらは機能的に、構造的にではないにしても同等です。 Firebugを使用してnew
を使用して作成されたオブジェクトを見ると、それらが同じであることがわかります。しかし、私の好みは次のようになります。私はC#/ Javaで慣れ親しんだものにもっと似ているように思えます。つまり、クラスを定義し、フィールド、コンストラクタ、およびメソッドを定義します。
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDIT変数のスコープが非公開であることを意味するのではなく、JavaScriptでクラスを定義する方法を説明しようとしていました。これを反映するように変数名が変更されました。
他の回答で説明したように、プロトタイプ内の関数は、インスタンス化ごとに作成される関数ではなく、すべてのインスタンス化と共有されているため、これは実際にはパフォーマンス上の考慮事項です。
これを示すためにjsperfをまとめました。クラスのインスタンス化にかかる時間には劇的な違いがありますが、実際には多くのインスタンスを作成している場合にのみ意味があります。
静的型付け言語について考えてみましょう。prototype
のことは静的で、this
のことはインスタンスに関連しています。