[英]Too much recursion error when a classfield is not declared
如果我们像这样声明一个 class:
class client{
constructor(name){
this.name = name
}
get name()
{
return this.name ;
}
set name(val)
{
this.name = val ;
}
}
实例化它会给出一个错误(太多的递归)并且这是正常的,因为 setter 会调用自己。
class client{ constructor(name){ this.name = name } get name() { return this.name; } set name(val) { this.name = val; } } let cl = new client();
但是当我将“名称”声明为 class 字段时,我没有收到该错误,我不明白为什么。
class client{ name = null; constructor(name){ this.name = name } get name() { return this.name; } set name(val) { this.name = val; } } let p = new client(); console.log(p);
TL;DR您不能在同一个 object 上同时拥有同名的数据属性和访问器属性,如果您在 object 上拥有数据属性,则不会使用其原型上具有相同名称的任何属性(除非你明确地这样做)。 name
class 字段定义在正在构造的 object 上创建了自己的数据属性。
在第一种情况下(我想你知道), name
setter 中的this.name
再次调用name
setter,递归直到你用完堆栈。 (吸气剂也一样,如果你用过的话。)
那么,当您在那里有那个name
字段定义时,有什么不同呢?
定义 class 字段的方式,该name
定义在正在创建的实例上创建了一个自己的属性,就好像您在构造函数的开头有这段代码(如果这是一个子类,就在super
调用之后):
constructor(name) {
// Definition of `name` field:
Object.defineProperty(this, "name", {
value: undefined,
writable: true,
configurable: true,
enumerable: true,
});
// Remainder of constructor code:
this.name = name;
}
因为它是一个own
属性,所以this.name
解析为该数据属性,而不是get name
和set name
访问器定义创建的原型上的访问器属性。 所以p
的原型上的那些访问器从未被使用过。
如果您查看第二个示例中属性的定义,您会发现:
class client { name = null; constructor(name){ this.name = name; } get name() { return this.name; } set name(val) { this.name = val; } } let p = new client(); console.log(p); console.log(Object.getOwnPropertyDescriptor(p, "name"));
如果你想拥有 accessor 属性,你可以使用一个私有字段,这是一个很新但在现代环境中受支持的字段:
class Client { #name = null; constructor(name) { this.#name = name; } get name() { return this.#name; } set name(val) { this.#name = val; } } let p = new Client("Joe"); console.log(p.name); console.log(Object.getOwnPropertyDescriptor(p, "name")); // undefined console.log(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(p), "name")); // accessor
.as-console-wrapper { max-height: 100%;important; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.