Использование сеттеров в Javascript для «переопределения» свойств - PullRequest
0 голосов
/ 17 сентября 2018

Страница MDN о set, кажется, утверждает, что

Сеттер [ECMAScript 2015] не должен появляться в литерале объекта ... с ввод данных для того же свойства.

Однако при использовании ключевого слова 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 голосов
/ 17 сентября 2018

Это кажется полезной функцией, поскольку свойство не нужно «скрывать», добавляя перед ним подчеркивание или что-то в этом роде. Кроме того, мне не нужно возиться с перечислимостью свойств, чтобы «скрытая» версия не отображалась в цикле или сериализации.

Нет, это не полезно. В лучшем случае это хак и не делает то, что вы ожидаете.

Здесь вообще ничего не скрыто. Вы создаете новое свойство с именем bar для самого экземпляра, скрывая все методы получения / установки, которые вы определили в прототипе. Второе назначение не получает ваш вызывающий абонент. Также свойство экземпляра является обычным перечисляемым свойством, поэтому оно будет отображаться в циклах for in и сериализации.

Также, что здесь означает "супер"?

Ключевое слово super относится к прототипу объекта, для которого определен метод (или метод установки), т.е. Object.getPrototypeOf(Foo.prototype). Это Object.prototype в вашем случае, поскольку ваш class Foo ничего не extend.

Доступ к .foo будет проверен на этом прототипе и, как правило, найдет метод, который вы унаследовали от родительского класса или чего-то еще. Однако при использовании ссылки на свойство super.foo получатель операции (т. Е. Что будет ключевым словом this в вызове метода) будет текущим экземпляром this, а не прототипом.

В вашем случае это не вызов метода, а присваивание. Это может запустить сеттер, унаследованный от родительского класса, но в вашем случае нет свойства Object.prototype.foo, поэтому он вернется к стандартному назначению для цели - и эта цель - сам экземпляр baz, где новое собственное свойство будет создан.

Так что нет, использовать его нельзя.

...