首页 > 解决方案 > 为什么惰性 getter 使用原型而不使用类?

问题描述

考虑以下代码:

const defclass = prototype => {
    const constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
};

const Person = defclass({
    constructor: function Person(firstname, lastname) {
        this.firstname = firstname;
        this.lastname  = lastname;
    },
    get fullname() {
        delete this.fullname; // doesn't delete on instances
        return this.fullname = this.firstname + " " + this.lastname;
    }
});

const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");

console.log(john.fullname); // John Doe
console.log(jane.fullname); // Jane Doe

这是有效的,因为属性分配this遮蔽了不存在的设置器。


现在,考虑使用 ES6 类的相同代码:

class Person {
    constructor(firstname, lastname) {
        this.firstname = firstname;
        this.lastname  = lastname;
    }

    get fullname() {
        delete this.fullname; // doesn't delete on instances
        return this.fullname = this.firstname + " " + this.lastname;
    }
}

const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");

console.log(john.fullname); // throws an error because there is no setter
console.log(jane.fullname);

这个答案中解释了它不起作用的原因。这是因为我们在原型链中找到了该属性,并且它没有设置器。那么,为什么当我们使用常规原型时不会抛出同样的错误呢?

注意:您可以删除带有delete关键字的行而不影响代码的行为。

标签: javascriptclassecmascript-6settergetter

解决方案


第一个代码我确实得到了同样的错误:

const defclass = prototype => {
    const constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
};

const Person = defclass({
    constructor: function Person(firstname, lastname) {
        this.firstname = firstname;
        this.lastname  = lastname;
    },
    get fullname() {
        "use strict";
//      ^^^^^^^^^^^^
        return this.fullname = this.firstname + " " + this.lastname;
    }
});

const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");

console.log(john.fullname); // John Doe
console.log(jane.fullname); // Jane Doe

只是class代码默认处于严格模式

在草率模式下,赋值不起作用,但被忽略,右侧的值是return从 getter 中编辑的。再次访问.fullname将再次运行 getter。


推荐阅读