懒惰的吸气剂在课堂上不起作用

IT技术 javascript ecmascript-6 getter
2021-03-05 14:09:25
class a {
    get b() {
        delete this.b;
        return this.b = 1;
    }
}

var c = {
    get b() {
        delete this.b;
        return this.b = 1;
    }
}

console.log(c.b); // works as expected
console.log((new a()).b); // throws error

上面的代码应该可以正常工作,但最后一行抛出。

未捕获的类型错误:无法设置只有 getter(...) 的 # 的属性 b

显然 getter 没有在类中被删除,而它在 object 中工作正常。我正在使用最新的稳定版 chrome。

Lazy Getter MDN 条目

3个回答

类的 getter 位于.prototype对象上,而不是 上this,这就是您尝试delete它失败的原因(并且,正如 Jeremy 指出的,它是不可删除的)。

然而,您可以简单地在隐藏 getter 的实例上创建一个自己的属性:

class a {
    get b() {
        Object.defineProperty(this, "b", { value: 1, writable: false, configurable: true })
        return this.b;
    }
}

var c = new a;
console.log(c.b); // 1

我们必须使用Object.defineProperty()一个简单的赋值来查找没有 setter 和 throws 的继承属性。

@Redu:尝试zz.b = 100,你会得到一个Uncaught RangeError: Maximum call stack size exceeded
2021-04-22 14:09:25
哦.. 跟踪一个吸气剂——这个想法从未在我脑海中闪过。这很酷。
2021-05-02 14:09:25
我只是做了class aa { get b() {return this.b;} set b(v) {this.b = v} },然后zz = new aa();aa.b = 100;然后aa.b;回报100预期。
2021-05-13 14:09:25
@Redu:那是无限递归?
2021-05-15 14:09:25
你只是在创造我认为你不需要所有仪式b财产a只要这样做get b() { return this.b } set b(v) {this.b = v},一切都会好起来的。
2021-05-20 14:09:25

按照设计,类属性不可删除——参考:https : //github.com/jeffmo/es-class-fields-and-static-properties

实例字段初始化过程

执行字段初始值设定项的过程发生在类实例化时。下面描述了初始化每个类字段初始化器的过程(旨在按照它们声明的顺序为每个字段运行一次):

  • 让 instance 成为被实例化的对象。
  • 令 fieldName 为当前字段的名称(存储在构造函数的槽中)。
  • 让 fieldInitializerExpression 成为当前字段的 thunked 初始化表达式(存储在构造函数的槽中)。
  • 令 initializerResult 是使用 this 等于 instance 对 fieldInitializerExpression 求值的结果。
  • 让 propertyDescriptor 为 PropertyDescriptor{[[Value]]: initializerResult, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false}。 调用实例。[[DefineOwnProperty]](fieldName, propertyDescriptor)。
这个问题中的任何内容都与提议的 ES 类属性语法无关。
2021-05-13 14:09:25
这是不正确的,规范链接和他们拥有的所有主要浏览器都可以配置:true 和 enumerable:false。对于对象字面量的属性,可枚举为真
2021-05-17 14:09:25

很明显,这是关于构造函数的。当您忽略构造函数时,您使用 getter 定义的属性将在构造函数原型中创建,因此完成这项工作的正确方法可能如下所示;

class a {
    get b() {
        delete this.constructor.prototype.b;
        return this.constructor.prototype.b = 1;
    }
}
z = new a();
z.b; // 1
你在什么环境下执行这个?正如上面 Jeremy 指出的那样,这应该加入 ES6。
2021-05-05 14:09:25
this.constructor.prototype当涉及到子类化时,引用通常是一个坏主意。a.prototype如果这就是您的意思,请明确引用
2021-05-08 14:09:25