Lazy getter doesn't work in classes

末鹿安然 提交于 2019-11-26 17:50:29

问题


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

The above code should work fine but the last line throws.

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

Clearly the getter is not being deleted in class whereas it works fine in object. I am on latest stable chrome.

Lazy Getter MDN Entry


回答1:


The getter of the class sits on the .prototype object, not on this, that's why your attempt to delete it fails (and, as Jeremy points out, it is not deletable).

You can however simply create an own property on the instance that shadows the 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

We have to use Object.defineProperty() as a simple assignment would find the inherited property that has no setter and throws.




回答2:


By design, class properties are not deletable -- reference: https://github.com/jeffmo/es-class-fields-and-static-properties

Instance Field Initialization Process

The process for executing a field initializer happens at class instantiation time. The following describes the process for initializing each class field initializer (intended to run once for each field in the order they are declared):

  • Let instance be the object being instantiated.
  • Let fieldName be the name for the current field (as stored in the slot on the constructor function).
  • Let fieldInitializerExpression be the thunked initializer expression for the current field (as stored in the slot on the constructor function).
  • Let initializerResult be the result of evaluating fieldInitializerExpression with this equal to instance.
  • Let propertyDescriptor be PropertyDescriptor{[[Value]]: initializerResult, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false}. Call instance.[[DefineOwnProperty]](fieldName, propertyDescriptor).



回答3:


Well obviously this is about constructors. When you neglect the constructor the property you define with the getter gets created at the constructors prototype hence the correct way of doing the job probably should be like as follows;

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


来源:https://stackoverflow.com/questions/37977946/lazy-getter-doesnt-work-in-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!