Может ли JS использовать методы getters и seters так же, как свойство?

Я хочу добиться такого поведения, как down в коде:

function Foo(name) {
    this.name = name;
};

var myFoo = new Foo('myName');

myFoo.name('newMyName'); // sets myFoo.name = 'newMyName'
myFoo.name(); // returns 'myName'

Но очевидно, что в этом случае я переопределяю свойство name с функцией имени. Как можно достичь этой функциональности?

Ответ 1

Говоря о геттерах и сеттерах в javascript, вы можете говорить об одном из двух понятий:

1. Getters и seters как концепция, как на любом другом языке OO.

Это пример, иллюстрируемый кодом в вашем вопросе. В этом случае свойство объекта - это просто свойство, которое может быть или быть либо объектом, либо функцией. javascript отслеживает как внутри одного пространства имен. Действительно, функции - это просто объекты в javascript, поэтому нет понятия отдельного пространства имен для таких функций, как вы могли бы найти на таких языках, как C.

В этом случае "getters" и "seters" являются просто регулярными функциями, поэтому значение нужно хранить отдельно. Существует несколько стратегий.

Один из них заключается в использовании неявных функций стиля getSomething() и setSomething(), которые обычно встречаются в Java. Это позволяет вам устранять неоднозначность геттеров и сеттеров из имени свойства, так как геттеры и сеттеры имеют слово "get" и "set", добавленное к имени.

Вторая стратегия - та, которую вы написали в своем вопросе. В этом случае вам нужно сохранить свойство под другим именем, чтобы не делиться одним и тем же именем с получателем/установщиком.

Третьей стратегией является сохранение значения в закрытии:

    function Foo (name) {
        var name = name;
        this.name = function (str) {
            if (str !== undefined) name = str;
            return name;
        }
    }

Обратите внимание, что в приведенном выше коде значение сохраняется в name, но getter/setter this.name, который является совершенно другой переменной. Это позволяет вашему примеру работать так, как вы ожидали:

    var me = new Foo('Mark');
    me.name(); // returns Mark
    me.name('Andy'); // sets name to Andy

2. Getters и seters как механизм в javascript.

Это особенность новых версий javascript, которые следуют спецификации ECMAscript 5. Эта функция позволяет свойствам выполнять код при чтении или записи на него, аналогично тому, как свойство .innerHTML объекта DOM вызывает парсер HTML, когда вы ему что-то присваиваете.

Синтаксис геттеров и сеттеров аналогичен функциям, но вместо function вводит ключевые слова get и set.

Простой пример свойства с геттером и сеттер:

    var me = {
        first_name : "",
        last_name : "",
        get name() {
            return this.first_name + " " + this.last_name;
        },
        set name(str) {
            var n = str.split(/\s+/);
            this.first_name = n.shift();
            this.last_name = n.join(' ');
        }
    }

Вышеприведенный код позволяет вам обрабатывать функции для получения и устанавливать first_name и last_name, как если бы это была переменная вместо функции. Чтобы использовать gett и setter name, вы просто выполните:

    me.name = "James Bond";
    alert(me.first_name); // should alert James
    alert(me.last_name); // should alert Bond
    me.last_name = "Dean";
    alert(me.name); // should alert James Dean

Используя механизм get/set javascript, вы не можете сохранить значение в объекте с использованием того же имени. Например:

    var foo = {
        set bar(x) {this.bar=x}
    }

Приведенный выше код скомпилируется, но пытается установить строку: foo.bar = 1 приведет к переполнению стека из-за бесконечного цикла - this.bar= внутри сеттера снова вызовет сеттер.