簡體   English   中英

Object.keys 返回私有屬性

[英]Object.keys returns private properties

我有使用 Typescript 創建的類/視圖模型。 我將此類中的一個字段設為私有,以便在我嘗試獲取所有其他類屬性時跳過它。

對嗎,我怎么能跳過我的私人財產?

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('');
}

TypeScript 編譯私有屬性就像常規屬性一樣,私有屬性的執行僅在編譯時完成,並且它們在運行時仍然存在。

github 上有很多要求即使在運行時也無法訪問私有屬性,但由於設計限制和/或哲學問題,這尚未實現,而且可能永遠不會實現。

您可以在此處閱讀一些設計討論歷史。

這意味着您必須使用自己的約定來處理此問題,例如在名稱前加上下划線並在循環中過濾該名稱。

private關鍵字僅影響 TypeScript 中的可見性,不影響 JS 輸出。

對於未在原型上定義的類屬性,因此無法使用類屬性裝飾器進行修改,最直接的方法是對私有屬性使用_命名約定:

class MyModel {
    // ...
    private _secretField = ko.observable('');
}

Object.keys(myObject)
    .filter(key => !(typeof key === 'string' && key.charAt(0) === '_'))
    .forEach(property => {
        // some stuff
    });

你可以從 ES6 開始使用 Symbols。 它可以存儲值並且不會出現在 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] 

TL;DR:使用私有標識符來定義您的私有字段。 這樣,它們的可訪問性也將在運行時強制執行。


正如已經指出的那樣,可訪問性僅由 TypeScript 轉譯器靜態地(在編譯時)強制執行。
因此,所有屬性,無論是公共的還是私有的,都作為普通的 JavaScript 屬性發出。 這里沒有魔法,除了使用Proxy來捕獲ownKeys()方法或使用Object.defineProperties而不是以 TypeScript 方式聲明它們之外,您無法做任何事情來隱藏它們。 對於后一個想法,我想出了一個例子:

class Foo {

    constructor() {

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

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

上面的例子可以在TypeScript Playground 中測試。

然而,我認為做這樣的事情是一種反模式,因為它破壞了所有的 TypeScript 安全性,這是選擇它而不是僅僅寫出 JavaScript 代碼的唯一原因。

因此,我們剩下的唯一解決方案是使用私有標識符 這是一個 TypeScript 功能,因此名稱以#開頭的任何字段不僅在編譯時而且在運行時都被強制為私有。

class Foo {

    #bar = "Hello world"

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

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

上面的例子可以在TypeScript Playground 中測試。

這是如何工作的? 好吧,您可能只是看看轉換后的 JavaScript 代碼,您會突然注意到一個WeakMap 實際上,對具有私有標識符的類中的每個字段都定義了對新WeakMap的引用,在定義它們的聲明類的同一詞法范圍內。 無論在何處訪問私有字段,都是通過調用 getter 或 setter 函數來完成的,該函數使用給定的映射(在引用該字段時傳遞)來獲取或設置給定鍵的值,該鍵是訪問該字段的類的實例上。 在 getter 和 setter 函數中也會進行運行時檢查,以便在使用未注冊的接收器調用時TypeError ,以防止使用不同類型的實例或根本沒有實例訪問私有字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM