JavaScriptでは、「クラス」を作成してパブリック関数を提供する方法が2つあります。
方法1:
function MyClass() {
var privateInstanceVariable = 'foo';
this.myFunc = function() { alert(privateInstanceVariable ); }
}
方法2:
function MyClass() { }
MyClass.prototype.myFunc = function() {
alert("I can't use private instance variables. :(");
}
私は何度も読んだことがあります 言って すべてのインスタンスがそれぞれの関数を取得するのではなく、すべてのインスタンスが同じ関数のコピーを共有するため、方法2を使用する方が効率的です。ただし、プロトタイプを介して関数を定義することには大きなデメリットがあります。プライベートインスタンス変数を持つことは不可能です。
理論的には、方法1を使用すると、オブジェクトの各インスタンスに関数の独自のコピーが提供されます(したがって、割り当てに必要な時間は言うまでもなく、より多くのメモリを使用します)。最適化Webブラウザーがこの非常に一般的なパターンを認識し、実際にオブジェクト参照のすべてのインスタンスを同じ関数のコピーにすることで簡単に作成できるようですこれらの「コンストラクター関数」を介して定義されます。その後、後で明示的に変更された場合にのみ、インスタンスに関数の独自のコピーを与えることができます。
両者のパフォーマンスの違いについての洞察-または、より良い実世界の経験-は、非常に役立ちます。
http://jsperf.com/prototype-vs-this を参照してください
プロトタイプを介してメソッドを宣言する方が高速ですが、これが適切かどうかは議論の余地があります。
アプリにパフォーマンスのボトルネックがある場合、たとえば、任意のアニメーションのすべてのステップで10000以上のオブジェクトをインスタンス化していない限り、これは起こりそうにありません。
パフォーマンスが深刻な問題であり、マイクロ最適化を行う場合は、プロトタイプを使用して宣言することをお勧めします。それ以外の場合は、最も意味のあるパターンを使用してください。
JavaScriptには、プライベートとして表示されることを意図したプロパティに下線を付けるという慣例があります(例:_process()
)。ほとんどの開発者は、社会契約を放棄するつもりがない限り、これらのプロパティを理解して回避しますが、その場合は、それらに対応しないこともできます。つまり、おそらくtrueプライベート変数は必要ないでしょう...
Chromeの新しいバージョンでは、this.methodはprototype.methodよりも約20%高速ですが、新しいオブジェクトの作成にはまだ時間がかかります。
常に新しいオブジェクトを作成する代わりにオブジェクトを再利用できる場合、これは新しいオブジェクトを作成するよりも50%から90%速くなります。さらに、ガベージコレクションを行わないことのメリットは非常に大きくなります。
多くのインスタンスを作成する場合にのみ、違いが生じます。それ以外の場合、メンバー関数を呼び出すパフォーマンスはどちらの場合でもまったく同じです。
これを実証するために、jsperfでテストケースを作成しました。
あなたはこれを考慮していなかったかもしれませんが、オブジェクトに直接メソッドを置くことは実際には一つの方法でより良いです:
ただし、速度の違いはほとんど無視できます。その上、プロトタイプにメソッドを配置することは、さらに2つの影響力のある方法で優れています。
Jamesが言ったように、クラスの数千のインスタンスをインスタンス化する場合、この違いは重要になる可能性があります。
つまり、各オブジェクトにアタッチしている関数がインスタンス間で変更されないことを認識し、すべてのインスタンスメソッドが共有関数を指すように、メモリに関数の1つのコピーのみを保持するJavaScriptエンジンを想像できます。実際、Firefoxはこのような特別な最適化を行っているようですが、Chromeはそうではありません。
ASIDE:
プロトタイプの内部メソッドからプライベートインスタンス変数にアクセスすることは不可能です。それで、あなたがあなた自身に尋ねなければならない質問は、継承とプロトタイピングの利用よりもインスタンス変数を本当にプライベートにすることができることを評価することでしょうか?私は個人的に、変数を本当にプライベートにすることはそれほど重要ではなく、アンダースコアプレフィックス(たとえば、「this._myVar」)を使用して、変数はパブリックですがプライベートであると見なされる必要があることを示します。とはいえ、ES6では、両方の世界の両方を持つ方法が明らかにあります。
このアプローチを使用すると、prototype
を使用してインスタンス変数にアクセスできるようになります。
var Person = (function () {
function Person(age, name) {
this.age = age;
this.name = name;
}
Person.prototype.showDetails = function () {
alert('Age: ' + this.age + ' Name: ' + this.name);
};
return Person; // This is not referencing `var Person` but the Person function
}()); // See Note1 below
注1:
括弧は関数(自己呼び出し関数)を呼び出し、その結果をvar Person
に割り当てます。
使用方法
var p1 = new Person(40, 'George');
var p2 = new Person(55, 'Jerry');
p1.showDetails();
p2.showDetails();
この回答は、不足しているポイントを埋める残りの回答の拡張と見なす必要があります。個人的な経験とベンチマークの両方が組み込まれています。
私の経験では、メソッドがプライベートであるかどうかに関係なく、コンストラクターを使用して文字通りオブジェクトを忠実に構築しています。主な理由は、私が始めたときそれが私への最も簡単な即時のアプローチであったので、それは特別な好みではないということです。それは私が目に見えるカプセル化が好きで、プロトタイプが少し具体化されているのと同じくらい単純だったかもしれません。私のプライベートメソッドもスコープ内の変数として割り当てられます。これは私の習慣であり、物事をうまく自己完結させていますが、常に最良の習慣であるとは限らず、壁にぶつかることもあります。構成オブジェクトとコードレイアウトに従って非常に動的な自己アセンブルを行う奇抜なシナリオは別として、特にパフォーマンスが懸念される場合、それは私の意見では弱いアプローチになる傾向があります。内部がプライベートであることを知ることは有用ですが、適切な規律で他の手段を介してそれを達成できます。パフォーマンスが重要な考慮事項でない限り、当面のタスクにはそれ以外の場合に最適に機能するものを使用してください。
prototype.m = f
、this.m = f
およびthis.m = function...
後者は、同じように機能する最初の2つよりも大幅に優れています。プロトタイプルックアップだけが重要な問題である場合、最後の2つの関数が最初の関数を大幅に実行します。代わりに、奇妙な何かが少なくともカナリアが関係しているところで起こっています。関数がメンバーであるものに従って最適化される可能性があります。パフォーマンスに関する多くの考慮事項が関係しています。パラメータアクセスと変数アクセスにも違いがあります。免責事項:
つまり、メソッド2を使用して、すべてのインスタンスが共有するプロパティ/メソッドを作成します。これらは「グローバル」になり、変更はすべてのインスタンスに反映されます。インスタンス固有のプロパティ/メソッドを作成するには、メソッド1を使用します。
もっと良いリファレンスがあればいいのですが、とりあえず this を見てください。同じプロジェクトで異なる方法で両方の方法を使用した方法を確認できます。
お役に立てれば。 :)