对象.Keys返回私有属性



我用Typescript创建了class/viewModel。我在这个类中设置了一个字段为私有,以便在我尝试获取所有其他类属性时跳过它。

是正确的,我怎么能跳过我的私有财产?

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

private关键字只影响TypeScript的可见性,不影响JS的输出。

对于没有在原型上定义的类属性,因此不能用类属性装饰器修改,最直接的方法是使用_命名约定的私有属性:

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

TypeScript编译私有属性就像编译普通属性一样,私密性的强制执行只在编译时完成,它们在运行时仍然存在。

在github上有很多请求使私有属性即使在运行时也无法访问,但由于设计限制和/或哲学问题,这还没有实现,而且可能永远不会实现。

你可以在这里阅读一些设计讨论历史。

这意味着您必须使用自己的约定来处理此问题,例如,在名称前加上下划线并在循环中过滤。

可以从ES6开始使用Symbols。它可以存储值,不会出现在对象中。钥匙结果

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,以防止使用不同类型的实例访问私有字段或根本没有实例。

相关内容

  • 没有找到相关文章

最新更新