无法理解类中的 Javascript setter 和 getter 查找

问题描述

我知道 JavaScript 类是原型之上的语法糖,不能作为其他 OOP 语言中的纯类工作。但是这里出现的问题是在 getter 和 setter 上。当在子类中完全离开 getter 和 setter 时,它的行为正常,但是如果我定义了 getter 或 setter 中的任何一个,就会破坏这些。

例如:

class A {
    constructor() {
        this.__value = "Default";
    }

    set value(value) {
        console.log("setter called")
        this.__value = value;
    }
    
    get value() {
        console.log("getter called")
        return this.__value;
    }
}

class B extends A {
    
}

let b = new B();
b.value = 2;
console.log(b.value);

上面的代码工作正常,但如果我在子类中定义 getter 或 setter,查找将不会转到父类。我用谷歌搜索了一下,发现它是故意的,并且是 ES 标准的。那么为什么当子类没有方法时,查找到达父类并能够访问getter和setter?

解决方法

当您访问对象属性时,无论是设置值 obj.prop = 'val' 还是检索值 console.log(obj.prop),引擎都会尝试在对象的原型链中查找该属性。

它从实例开始。在这种情况下,实例没有任何属性,所以它继续。

下一个对象是实例的内部原型,即B.prototype。如果 B 有正在查看的属性名称,它会停在那里。如果有一个 setter,并且为该属性分配了一个值,则将调用该 setter。如果有 getter 并且正在检索值,则将调用 getter。

就是这样 - 一旦在原型链中找到一个属性,它就会停止搜索。

如果 B.prototype 没有 setter/getter,那么引擎将继续处理 next 对象。 B.prototype 的内部原型是 A.prototype。然后,将调用 A 的 setter 或 getter。

可以从子类调用超类的 setter/getter,但看起来有点奇怪:

class A {
    constructor() {
        this.__value = "Default";
    }

    set value(value) {
        console.log("setter called")
        this.__value = value;
    }
    
    get value() {
        console.log("getter called")
        return this.__value;
    }
}

class B extends A {
    set value(value) {
        console.log('sub setter calling super');
        super.value = value;
    }
    get value() {
        console.log('sub getter calling super');
        return super.value;
    }
}

let b = new B();
b.value = 2;
console.log(b.value);

,

在谷歌搜索和大量代码执行后,我找到了我自己问题的答案,如果我们在子类中没有定义访问器(getter 或 setter),查找将继续向父类进行,但如果我们使用 {{ 1}} 或 get 子类中的描述符将调用 set 方法并设置我们提到的描述符。如果我们有 setter 和 getter 没有问题,但如果我们留下任何一个导致到我们当前对象中缺少这些属性。这就是我们得到 Object.defineProperty 的原因,因为未定义的属性得到 undefined 值。所以从字面上看,我们已经找到了 undefined 的值,这是主要的原因是我们无法继续访问父原型作为在当前对象中找到的 value(undefined) 并且查找将停止。