0

Typescriptで作成されたクラス/ビューモデルがあります。他のすべてのクラス プロパティを取得しようとするときにスキップするために、このクラスの 1 つのフィールドをプライベートとして作成しました。

それは正しいですか、どうすれば私の私有財産をスキップできますか?

Object.keys(myObject).forEach(property => {
        //some stuff
     }
});

私のクラスの例:

class MyModel{
    id: any = ko.observable('');
    name: any = ko.observable('');

    address: any = ko.observable('');
    city: any = ko.observable('');
    state: any = ko.observable('');
    country: any = ko.observable('');

    private secretField= ko.observable('');
}
4

4 に答える 4

4

TypeScript は、通常のプロパティと同様にプライベート プロパティをコンパイルします。プライベート性の適用はコンパイル時にのみ行われ、実行時にも存在します。

github には、実行時にもプライベート プロパティにアクセスできないようにするという多くの要求がありますが、設計上の制限や哲学的な問題により、これは実装されておらず、今後も実装されない可能性があります。

ここで設計に関する議論の歴史を読むことができます。

つまり、これを処理するには、独自の規則を使用する必要があることを意味します。たとえば、名前の前にアンダースコアを付けてループでフィルタリングするなどです。

于 2016-11-04T17:41:56.500 に答える
0

ES6 からシンボルを使用できます。値を保存でき、Object.keys の結果には表示されません

JS コード

const privateStuff = Symbol()
var obj = {
  name: "Andrew",
  age: 23,
  [privateStuff]: "Don't show it"  
}

var keys = Object.keys(obj);
keys.forEach((k)=>{console.log(k)});

//get value
var serverStuff=obj[privateStuff] 
于 2020-08-26T23:32:03.417 に答える
0

TL;DR:プライベート識別子を使用してプライベート フィールドを定義します。このようにして、アクセシビリティは実行時にも適用されます。


既に指摘したように、アクセシビリティは、TypeScript トランスパイラーによって (コンパイル時に) 静的にのみ適用されます。
したがって、パブリックまたはプライベートのすべてのプロパティは、通常の JavaScript プロパティとして発行されます。ここには魔法はありません。メソッドProxyをトラップするためにa を使用するか、TypeScript の方法で宣言するのではなく使用する以外に、それらを非表示にすることはできません。後者のアイデアについては、次の例を考えました。ownKeys()Object.defineProperties

class Foo {

    constructor() {

        Object.defineProperties(this, {
            bar: {
                enumerable: false,
                value: "Hello world"
            }
        })

        console.log((this as any).bar)
    }
}

上記の例はTypeScript Playgroundでテストできます。

しかし、私はそのようなことをするのはアンチパターンだと思います。TypeScript の安全性をすべて壊してしまうからです。それが、単に JavaScript コードを書き出すのではなく、TypeScript を選択する唯一の理由です。

したがって、残された唯一の解決策は、プライベート識別子を使用することです。これは TypeScript の機能であり、名前が で始まるフィールド#はコンパイル時だけでなく実行時にもプライベートとして適用されます。

class Foo {

    #bar = "Hello world"

    constructor() {
        console.log(this.#bar)
    }
}

console.log(Object.keys(new Foo()))

上記の例はTypeScript Playgroundでテストできます。

それはどのように機能しますか?トランスパイルされた JavaScript コードを見ただけで、突然WeakMap. 実際、new への参照WeakMapは、プライベート識別子を持つクラスのすべてのフィールドに対して、それらの宣言クラスが定義されているのと同じレキシカル スコープで定義されます。プライベート フィールドにアクセスする場合は常に、特定のマップ (そのフィールドを参照するときに渡される) を使用するゲッターまたはセッター関数を呼び出して、フィールドにアクセスするためのクラスのインスタンスである特定のキーで値を取得または設定します。の上。ゲッター関数とセッター関数の両方で実行時チェックも行われ、TypeError登録されていないレシーバーで呼び出したときに a がスローされ、プライベート フィールドが異なる型のインスタンスでアクセスされたり、インスタンスがまったくアクセスされたりするのを防ぎます。

于 2020-10-14T14:08:20.953 に答える