惰性 getter 在 类 中不起作用

Lazy getter doesn't work in classes

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

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

Uncaught TypeError: Cannot set property b of # which has only a getter(…)

显然 getter 没有在 class 中被删除,而它在对象中工作正常。我在最新的稳定 chrome.

Lazy Getter MDN Entry

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

实例字段初始化过程

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

  • 让实例成为被实例化的对象。
  • 设 fieldName 为当前字段的名称(存储在构造函数的槽中)。
  • 设 fieldInitializerExpression 为当前字段的 thunked 初始化表达式(存储在构造函数的槽中)。
  • 设 initializerResult 为 fieldInitializerExpression 的求值结果,它等于 instance。
  • 设propertyDescriptor为PropertyDescriptor{[[Value]]: initializerResult, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false}. 调用实例。[[DefineOwnProperty]](fieldName, propertyDescriptor).

class 的 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 并抛出的继承 属性。

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

class a {
    get b() {
        delete this.constructor.prototype.b;
        return this.constructor.prototype.b = 1;
    }
}
z = new a();
z.b; // 1