javascript - 我可以使用变量作为标识符来设置私有类字段吗?如何?
问题描述
Node.js 12 支持由# out-of-the-box 表示的私有类字段,没有标志或转译器。
例如,这适用于 Node.js 12:
class Foo {
#bar = 1;
constructor({ bar }) {
this.#bar = bar;
}
get bar() {
return this.#bar;
}
}
const foo = new Foo({ bar: 2 });
console.log(foo.bar); // 2
假设我想用 20 而不是 1 个属性来构造我的 Foo 实例——我必须将构造函数和 getter 函数中的赋值语句复制 20 次,这会产生很多样板代码。
如果我不使用私有字段而是使用常规类字段,这不难避免:
class Foo {
bar = 1;
constructor(properties) {
Object.entries(properties).forEach(([name, value]) => (this[name] = value));
}
get bar() {
return this.bar;
}
}
const foo = new Foo({ bar: 2 });
console.log(foo.bar); // 2
但是,对于私有类字段,它不起作用:
class Foo {
#bar = 1;
constructor(properties) {
Object.entries(properties).forEach(
([name, value]) => (this[`#${name}`] = value)
);
}
get bar() {
return this.#bar;
}
}
const foo = new Foo({ bar: 2 });
console.log(foo.bar); // 1 :-(
我还尝试使用Reflect.set为构造函数中的私有类字段赋值,但无济于事:
class Foo {
#bar = 1;
constructor(properties) {
Object.entries(properties).forEach(([name, value]) =>
Reflect.set(this, `#${name}`, value)
);
}
get bar() {
return this.#bar;
}
}
const foo = new Foo({ bar: 2 });
console.log(foo.bar); // 1 :-(
我可以使用变量作为标识符来设置私有类字段吗?如果是,如何?
解决方案
不,这看起来不可能。从提案常见问题解答:
为什么 this['#x'] 不访问名为 #x 的私有字段,因为 this.#x 可以?
这会使属性访问语义复杂化。
对私有字段的动态访问与“私有”的概念相反。例如,这是关于:
class Dict extends null { #data = something_secret; add(key, value) { this[key] = value; } get(key) { return this[key]; } } (new Dict).get('#data'); // returns something_secret
语法是这样的,每个私有字段必须#
在文字属性名称之前初始化和/或引用,仅此而已。甚至不允许使用括号表示法。
拥有一个名为 x 的私有字段不能阻止有一个名为 x 的公共字段,因此访问私有字段不能只是正常的查找。
除非在类主体中明确定义(不是类函数,而是直接在类主体中),否则您甚至不能引用私有字段:
class Foo {
// error is thrown because #abc must be defined in this section
doSomething() {
return this.#abc;
}
}
也就是说,没有什么能阻止你创建一个私有属性,它是一个对象,所有这些属性都在对象上:
class Foo {
#privates = {};
constructor(properties) {
Object.entries(properties).forEach(
([name, value]) => (this.#privates[name] = value)
);
}
get privates() {
return this.#privates;
}
}
const foo = new Foo({ bar: 2 });
console.log(foo.privates.bar);
推荐阅读
- python - python:如何将类函数结果分配给同一类中的类变量
- android - 如何从片段打开新视图?
- android - 在片段内调用 RecyclerView 适配器方法
- javascript - iOS 11.4 Safari 不尊重“触摸动作:操纵”
- java - 如何让一个按钮在每次按下时随机播放声音列表?
- date - bat 脚本 - 仅在给定的多个不同日期运行命令
- mysql - 如何在 SELECT 语句的列部分使用从 DATE_FORMAT() 返回的值
- html - Bootstrap 卡中的左对齐按钮
- regex - 我可以在我想要的字符串之前或之后 grep 一定数量的行吗?
- java - jmDNS Ubuntu IP 解析地址错误