0

我有使用 Typescript 创建的类/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('');
}
4

4 回答 4

5

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

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

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

Object.keys(myObject)
    .filter(key => !(typeof key === 'string' && key.charAt(0) === '_'))
    .forEach(property => {
        // some stuff
    });
于 2016-11-04T17:58:12.880 回答
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来捕获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定义其声明类的相同词法范围内,为具有私有标识符的类中的每个字段定义了对 new 的引用。无论在何处访问私有字段,都通过调用使用给定映射(在引用该字段时传递)的 getter 或 setter 函数来获取或设置给定键的值,这是访问该字段的类的实例在。还在 getter 和 setter 函数中进行运行时检查,以便TypeError在使用未注册的接收者调用时抛出 a ,以防止私有字段被不同类型的实例或根本没有实例访问。

于 2020-10-14T14:08:20.953 回答