在Javascript中使用setter来“覆盖”属性

问题描述 投票:3回答:1

MDN page about set似乎表明了一个

[ECMAScript 2015] setter不得出现在对象文字中...带有相同属性的数据条目。

但是,当使用super关键字时,这似乎不再适用。

class Foo {
    constructor(bar){
        this.bar = bar
    }

    set bar(newBar){
        if (!newBar.match(/\w+/))
            throw Error("Invalid bar value")
        // I can use super despite not being a derived class.
        return super.bar = newBar
    }
}
const baz = new Foo("Baz")
baz.bar = "new value" // No recursion

这似乎是一个有用的功能,因为该属性不必通过在其前面添加下划线来“隐藏”。另外,我不必弄乱属性可枚举性,以避免“隐藏”版本在循环或序列化中显示。

set语法有点像黑盒子,我无法分辨它究竟在做什么。

我在这里打破一些东西还是可以使用?

还有什么是super在这里引用?

javascript oop ecmascript-6 setter super
1个回答
2
投票

这似乎是一个有用的功能,因为该属性不必通过在其前面添加下划线或其他内容来“隐藏”。另外,我不必弄乱属性可枚举性,以避免“隐藏”版本在循环或序列化中显示。

不,它没用。这是一个充其量的黑客,并没有做你期望的。

这里根本没有隐藏的东西。您正在实例上创建一个名为bar的新属性,隐藏您在原型上定义的任何getter / setter。第二个作业没有得到你的二传手。实例属性也是普通的可枚举属性,因此它将显示在for in循环和序列化中。

那么什么是“超级”引用?

super关键字指的是定义方法(或设置器)的对象的原型,即Object.getPrototypeOf(Foo.prototype)。这是你的情况下的Object.prototype,因为你的class Foo没有extend任何东西。

将在该原型上查找.foo访问,并且通常会找到您从父类或其他东西继承的方法。当使用它时,属性引用super.foo将使操作的接收者(即方法调用中的this关键字是什么)是当前的this实例,而不是原型。

在您的情况下,它不是方法调用而是分配。这可以运行从父类继承的setter,但是在你的情况下没有Object.prototype.foo属性,所以它将回退到目标上的标准赋值 - 并且该目标是baz实例本身,其中将创建新的自己的属性。

所以不,使用它是不对的。

© www.soinside.com 2019 - 2024. All rights reserved.