TypeScriptでのプライベートメンバーの実装を調べていますが、少し混乱しています。Intellisenseはプライベートメンバーへのアクセスを許可していませんが、純粋なJavaScriptではそれだけです。これにより、TSはプライベートメンバーを正しく実装しないと思います。何かご意見は?
class Test{
private member: any = "private member";
}
alert(new Test().member);
TypeScriptでのプライベートメンバーの実装を調べていますが、少し混乱しています。Intellisenseはプライベートメンバーへのアクセスを許可していませんが、純粋なJavaScriptではそれだけです。これにより、TSはプライベートメンバーを正しく実装しないと思います。何かご意見は?
class Test{
private member: any = "private member";
}
alert(new Test().member);
回答:
型チェックと同様に、メンバーのプライバシーはコンパイラー内でのみ適用されます。
プライベートプロパティは通常のプロパティとして実装され、クラス外のコードはそれにアクセスできません。
クラス内で何かを本当にプライベートにするには、それをクラスのメンバーにすることはできません。オブジェクトを作成するコード内の関数スコープ内に作成されるローカル変数になります。つまり、クラスのメンバーのように、つまりthisキーワードを使用してアクセスすることはできません。
thisキーワードを使用してアクセスすることはできません。
JavaScriptはプライベート変数をサポートします。
function MyClass() {
var myPrivateVar = 3;
this.doSomething = function() {
return myPrivateVar++;
}
}
TypeScriptでは、これは次のように表現されます。
class MyClass {
doSomething: () => number;
constructor() {
var myPrivateVar = 3;
this.doSomething = function () {
return myPrivateVar++;
}
}
}
編集
このアプローチは、絶対に必要な場合にのみ、一時的に使用する必要があります。たとえば、パスワードを一時的にキャッシュする必要がある場合です。
このパターン(JavascriptまたはTypescriptとは無関係)を使用するとパフォーマンスが低下するため、絶対に必要な場合にのみ使用してください。
var _this、スコープ関数で使用するように設定することで、常にこれを行いませんか?なぜクラススコープでそれをしているのでしょうか?
WeakMapのサポートがより広く利用できるようになると、ここの例3 で詳しく説明する興味深い手法があります。
インスタンスメソッドだけでなくプロトタイプメソッドからデータにアクセスできるようにすることで、プライベートデータを許可し、Jason Evansサンプルのパフォーマンスコストを回避します。
リンクされたMDN WeakMapページには、Chrome 36、Firefox 6.0、IE 11、Opera 23、およびSafari 7.1でのブラウザーサポートがリストされています。
let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
decrement() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
protectedパラメータのサポートを追加してみませんか?:D
TypeScript 3.8がリリースされると、アクセスできない、または含まれているクラスの外部で検出できないプライベートフィールドを宣言できるように なります。
class Person {
#name: string
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, my name is ${this.#name}!`);
}
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name
// ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.
プライベートフィールドは#文字で始まります
これらのプライベートフィールドは、privateキーワードでマークされたフィールドとは異なることに注意してください
参照 https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/
この問題に関する公式ディスカッションへのリンクを提供してくれたSean Feldmanに感謝します。リンクについては彼の回答を参照してください。
私は彼がリンクした議論を読みました、そしてここに重要なポイントの要約があります:
thisある種の回避策がないとアクセスできません@private注釈を付けると、その注釈を認識するミニファイアでメソッド名を効果的に縮小できます
放出されたコードに可視性サポートを追加することに対する全体的な反論:
TypeScriptでは、プライベート関数はクラス内でのみアクセスできます。お気に入り
プライベートメンバーにアクセスしようとすると、エラーが表示されます。次に例を示します。
注:javascriptでは問題なく、両方の機能に外部からアクセスできます。
これは古い議論であることはわかっていますが、TypeScriptのプライベート変数とメソッドの可能性がある問題の解決策を、コンパイルされたJavaScriptクラスのパブリックインターフェイスに「漏出」することを共有すると役立つ場合があります。
私にとって、この問題は純粋に表面的なものです。つまり、DevToolsでインスタンス変数が表示されるときの視覚的な混乱がすべてです。私の修正は、プライベート宣言を別のクラス内でグループ化して、メインクラスでインスタンス化し、(ダブルアンダースコア)のprivateような名前で(ただし、JSでパブリックに表示される)変数に割り当てること__です。
例:
class Privates {
readonly DEFAULT_MULTIPLIER = 2;
foo: number;
bar: number;
someMethod = (multiplier: number = this.DEFAULT_MULTIPLIER) => {
return multiplier * (this.foo + this.bar);
}
private _class: MyClass;
constructor(_class: MyClass) {
this._class = _class;
}
}
export class MyClass {
private __: Privates = new Privates(this);
constructor(foo: number, bar: number, baz: number) {
// assign private property values...
this.__.foo = foo;
this.__.bar = bar;
// assign public property values...
this.baz = baz;
}
baz: number;
print = () => {
console.log(`foo=${this.__.foo}, bar=${this.__.bar}`);
console.log(`someMethod returns ${this.__.someMethod()}`);
}
}
let myClass = new MyClass(1, 2, 3);
ときにmyClassインスタンスがデベロッパーツールで表示され、代わりにそのすべての「プライベート」のメンバーを見てのあなたがそれらをきちんと折りたたま内でグループ化された参照(非常に視覚的に適切にリファクタリング実際のコードに厄介にすることができます)本当に公共のものと混在し__プロパティ:
適切なプライベートプロパティを追加するための再利用可能なアプローチを次に示します。
/**
* Implements proper private properties.
*/
export class Private<K extends object, V> {
private propMap = new WeakMap<K, V>();
get(obj: K): V {
return this.propMap.get(obj)!;
}
set(obj: K, val: V) {
this.propMap.set(obj, val);
}
}
Client2つのプライベートプロパティを必要とするクラスがあるとします。
prop1: stringprop2: number以下はそれを実装する方法です:
// our private properties:
interface ClientPrivate {
prop1: string;
prop2: number;
}
// private properties for all Client instances:
const pp = new Private<Client, ClientPrivate>();
class Client {
constructor() {
pp.set(this, {
prop1: 'hello',
prop2: 123
});
}
someMethod() {
const privateProps = pp.get(this);
const prop1 = privateProps.prop1;
const prop2 = privateProps.prop2;
}
}
そして、必要なのが単一のプライベートプロパティだけの場合は、ClientPrivateその場合は何も定義する必要がないため、さらに簡単になります。
注目に値するのは、ほとんどの場合、クラスPrivateは読みやすい署名を提供するだけですが、直接使用する場合はWeakMapそうではありません。