Каков аргумент в пользу использования получателей и установщиков ES6 по соглашению getProperty/setProperty?

class Foo {
    getName = () => this.name;

    setName = (name) => this.name = name;
}

и

class Foo {
    get name () {
        return this.name;
    }

    set name (name) {
        this.name = name;
    }
}

Я могу представить несколько примеров, в которых получатели ES6 находятся в невыгодном положении, например

Вы не можете записать получателя, который вернет значение, основанное на значении параметра:

/**
 * Returns an instance of Card associated with an element.
 *
 * @param {HTMLElement} element
 * @return {Card|undefined}
 */
getCard = (element) => {
    return _.find(this.index, {
        element: element
    });
};

Однако, если вы используете это и ES6, вы вводите несогласованность в стиле кода.

Вы не можете различать прямой доступ к свойствам и доступ к методу.

class Foo {
    get name () {
        return this.name;
    }

    get expensive () {
        // An operation that takes a lot of computational power.
    }

    get randomValue () {
        // Returns random value.
    }
}

let foo = Foo();

foo.name;
foo.expensive;
foo.randomValue;

Недостаток заключается в том, что не интуитивно понятно, что для свойства, к которому вы обращаетесь, может потребоваться большая вычислительная мощность (и, следовательно, его следует помнить) или что он изменяется каждый раз, когда вы обращаетесь к нему.

Наконец, getters/seters не работают с функциями стрелок. Недопустимый пример:

class Foo {
    get name = () => {
        return this.name;
    }

    set name = (name) => {
        this.name = name;
    }
}

который подвергает их проблемам контекста.

Что такое преимущество использования получателей и сеттеров ES6 по сравнению с обычной абстракцией get{PropertyName} и set{PropertyName}?

Ответ 1

Вы не можете различать прямой доступ к свойствам и доступ к методу.

Это главный аргумент в их пользу.

Одна из самых страшных попыток написания классического кода OO для Java-стиля заключается в том, что любой объект с открытым свойством на нем должен иметь письменные записи и сеттеры, и из этого выйдет огромное количество шаблонов, особенно для больших объекты типа структуры данных (например, DTOs).

Обоснование всего этого состоит в том, что вы не можете просто сделать свойства общедоступными, потому что в противном случае вы никогда не сможете добавлять к ним логику, не нарушая API (например, логику, чтобы разрешать только определенные значения или рефакторировать и хранить свойство несколько по-другому, при этом все же выставляя один и тот же внешний API или аналогичный). См. https://softwareengineering.stackexchange.com/questions/176876/why-shouldnt-i-be-using-public-variables-in-my-java-class для некоторых типичных аргументов вокруг этого.

Я думаю, вы могли бы с уверенностью сказать, что в последние годы это было доведено до логического предела, но это не значит, что это неправильно; выставляя публичное поле для прямого доступа, вы действительно подвергаете внутреннюю реализацию того, как вы храните эти данные, а это означает, что вы не можете изменить его как легко или безопасно.

Получатели/сеттеры ES6 исправляют это. Тот факт, что что-то читается как прямое свойство объекта, больше ничего не говорит о реализации этого свойства. Это могло быть полем первоначально, но в последнее время оно превратилось в аксессуар свойств ES6 вместо этого, без изменения API. Реализация свойства скрыта от остальной части вашей кодовой базы и поэтому легче изменить.

Недостаток заключается в том, что не интуитивно понятно, что для свойства, к которому вы обращаетесь, может потребоваться большая вычислительная мощность (и, следовательно, его следует помнить) или что он изменяется каждый раз, когда вы обращаетесь к нему.

Вы правы, это риск. Это также gotcha с любым getX(); существует сильное соглашение о том, что хорошие простые методы, такие как "getName()", никогда не должны делать дорогостоящие вещи за кулисами, даже если они являются методами, и если вы нарушите это, вы почти наверняка поймаете людей (в том числе себя, через 6 месяцев)

Перемещение к свойствам не изменяет этого, но вы правы, что ES6 означает, что вам больше не гарантируется безопасность для простых доступов к свойствам. Ответ на самом деле заключается в том, что вы должны убедиться, что вы (и все остальные) придерживаетесь соглашения и Принцип наименьшего удивления: как с существующим простым ищущие геттеры и сеттеры, аксессоры доступа ES6 должны делать простые дешевые вещи и не должны иметь странных побочных эффектов в других местах.

Ответ 2

Нет никаких конкретных вещей, которые вы не можете сделать с getMethod() и setMethod(), но это позволяет использовать разные стили кода. Например, с get foo и set foo вы могли бы написать:

obj.foo++;

который будет называть геттер, а затем сеттер. Разумеется, вы могли бы использовать функцию set, а затем проверить, что это значение находится в определенном диапазоне, например. Традиционный код будет выглядеть так:

obj.setFoo(obj.getFoo() + 1);

Вы не можете различать прямой доступ к свойствам и доступ к методу.

Вот что. Я бы сказал, что если что-то действительно дорого, вы просто не должны использовать геттеры для него.