質問: new something(); console.log(instance.property); //=> "test"
回答: @ loganfsmythの答えを詳しく説明すると、javascriptの唯一の真のプライベートデータは、まだスコープ変数です。パブリックプロパティと同じ方法でプロパティにアクセスするという意味でプライベートプロパティを持つことはできませんが、スコープ付き変数を使用してプライベートデータを格納することはできます。スコープ変数ここでのアプローチは、プライベートデータを格納するために、プライベートなコンストラクタ関数のスコープを使用することです。メソッドがこのプライベートデータにアクセスできるようにするには、それらもコンストラクタ内で作成する必要があります。つまり、すべてのインスタンスでそれらを再作成します。これはパフォーマンスとメモリのペナルティですが、ペナルティは許容できると考える人もいます。通常の方法でプロトタイプに追加することで、プライベートデータにアクセスする必要がないメソッドのペナルティを回避できます。例:function person(name) { let age = 20; // this is private this.name = name; // this is public this.greet = function () { // here we can access both name and age console.log(`name: ${this.name}, age: ${age}`); }; } let joe = new person('joe'); joe.greet(); // here we can access name but not age スコープ付き弱いマップweakmapを使用すると、以前のアプローチのパフォーマンスとメモリのペナルティを回避できます。 weakmapsは、そのweakmapを使用した場合にのみアクセスできるように、データをオブジェクト(ここではインスタンス)と関連付けます。そのため、スコープ付き変数メソッドを使用してプライベートweakmapを作成し、そのweakmapを使用してthisに関連付けられたプライベートデータを取得します。すべてのインスタンスが単一のweakmapを共有できるため、これはスコープ変数メソッドよりも高速です。したがって、独自のweakmapにアクセスするためだけにメソッドを再作成する必要はありません。例:let person = (function () { let privateprops = new weakmap(); class person { constructor(name) { this.name = name; // this is public privateprops.set(this, {age: 20}); // this is private } greet() { // here we can access both name and age console.log(`name: ${this.name}, age: ${privateprops.get(this).age}`); } } return person; })(); let joe = new person('joe'); joe.greet(); // here we can access joe's name but not age この例では、objectを使用して、複数のプライベートプロパティに対して1つのweakmapを使用しています。複数のweakmapを使ってage.set(this, 20)のように使うことも、小さなラッパーを書いてprivateprops.set(this, 'age', 0)のように別の方法で使うこともできます。このアプローチのプライバシーは、グローバルなweakmapオブジェクトを改ざんすることによって理論上侵害される可能性があります。とは言っても、すべてのjavascriptは壊れたグローバルによって破壊される可能性があります。私たちのコードは、これが起こっていないという前提で既に構築されています。(このメソッドはmapでも実行できますが、weakmapは特に注意しない限りメモリリークを起こすため、mapの方が優れています。この目的のために、この2つの点で違いはありません)。半回答:スコープ記号シンボルは、プロパティ名として使用できるプリミティブ値の一種です。スコープ付き変数メソッドを使用してプライベートシンボルを作成し、プライベートデータをthis[mysymbol]に格納することができます。このメソッドのプライバシーはobject.getownpropertysymbolsを使用して侵害される可能性がありますが、やや面倒です。例:let person = (function () { let agekey = symbol(); class person { constructor(name) { this.name = name; // this is public this[agekey] = 20; // this is intended to be private } greet() { // here we can access both name and age console.log(`name: ${this.name}, age: ${this[agekey]}`); } } return person; })(); let joe = new person('joe'); joe.greet(); // here we can access joe's name and, with a little effort, age. agekey is // not in scope, but we can obtain it by listing all symbol properties on // joe with `object.getownpropertysymbols(joe)`. 半回答:アンダースコア古いデフォルトでは、アンダースコアの接頭辞を付けたpublicプロパティを使うだけです。いかなる意味においても私有財産ではないが、この慣習は読者がその財産を私有財産として扱うべきであることを伝える良い仕事をするほど十分に普及している。この経過と引き換えに、読みやすく、入力しやすく、そしてより速いアプローチが得られます。例:class person { constructor(name) { this.name = name; // this is public this._age = 20; // this is intended to be private } greet() { // here we can access both name and age console.log(`name: ${this.name}, age: ${this._age}`); } } let joe = new person('joe'); joe.greet(); // here we can access both joe's name and age. but we know we aren't // supposed to access his age, which just might stop us. 結論es2017の時点で、私有財産をするのに完璧な方法はまだありません。さまざまなアプローチには長所と短所があります。スコープ付き変数は本当にプライベートです。スコープ付きweakmapはスコープ付き変数よりも非常に非公開で実用的です。スコープ付きシンボルは適度に非公開で適度に実用的です。アンダースコアは、十分に非公開で非常に実用的です。