使用Java中的setter来“覆盖”属性

时间:2018-09-17 12:20:08

标签: javascript oop ecmascript-6 setter super

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指的是什么?

1 个答案:

答案 0 :(得分:2)

  

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

不,它没有用。充其量是骇客,它并没有达到您的期望。

这里根本没有隐藏任何东西。您将在实例本身上创建一个名称为bar的新属性,从而使您在原型上定义的所有getter / setter方法都没有效果。第二项任务没有让您的setter呼叫者获得。而且instance属性是普通的可枚举属性,因此它将以for in循环和序列化形式显示。

  

这里的“超级”是什么?

super关键字是在其上定义方法(或设置方法)的对象的原型,即Object.getPrototypeOf(Foo.prototype)。这是您的情况下的Object.prototype,因为您的class Fooextend什么。

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

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

因此,不可以使用。