我可以使用变量作为标识符来设置私有 class 字段吗?如何?
Can I set a private class field using a variable as identifier? How?
Node.js 12 支持 private class fields denoted by # 开箱即用,没有标志或转译器。
例如,这适用于 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
假设我不想用 1 属性 而是用 20 构造我的 Foo 实例——我将不得不在构造函数和 getter 函数中复制赋值语句 20 次,这大量样板代码。
如果我不使用私有字段而是使用常规 class 字段,这将不难避免:
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 字段,它不起作用:
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 字段赋值,但无济于事:
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 :-(
我可以使用变量作为标识符来设置私有 class 字段吗?如果是,如何?
不,这看起来不可能。来自 proposal FAQ:
Why doesn't this['#x'] access the private field named #x, given that this.#x does?
This would complicate property access semantics.
Dynamic access to private fields is contrary to the notion of 'private'. E.g. this is concerning:
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
语法是这样的,每个私有字段都必须初始化 and/or 在文字 属性 名称之前用 #
引用,除此之外别无其他。连括号符号都不允许。
Having a private field named x must not prevent there from being a public field named x, so accessing a private field can't just be a normal lookup.
您甚至不能引用私有字段,除非它在 class 正文中明确定义( 不是 一个 class 函数,但在 class正文直接):
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);
Node.js 12 支持 private class fields denoted by # 开箱即用,没有标志或转译器。
例如,这适用于 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
假设我不想用 1 属性 而是用 20 构造我的 Foo 实例——我将不得不在构造函数和 getter 函数中复制赋值语句 20 次,这大量样板代码。
如果我不使用私有字段而是使用常规 class 字段,这将不难避免:
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 字段,它不起作用:
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 字段赋值,但无济于事:
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 :-(
我可以使用变量作为标识符来设置私有 class 字段吗?如果是,如何?
不,这看起来不可能。来自 proposal FAQ:
Why doesn't this['#x'] access the private field named #x, given that this.#x does?
This would complicate property access semantics.
Dynamic access to private fields is contrary to the notion of 'private'. E.g. this is concerning:
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
语法是这样的,每个私有字段都必须初始化 and/or 在文字 属性 名称之前用 #
引用,除此之外别无其他。连括号符号都不允许。
Having a private field named x must not prevent there from being a public field named x, so accessing a private field can't just be a normal lookup.
您甚至不能引用私有字段,除非它在 class 正文中明确定义( 不是 一个 class 函数,但在 class正文直接):
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);