Javascript-геттеры и сеттеры — проблема рекурсии

#javascript #oop

#javascript #рекурсия #getter-сеттер

Вопрос:

Может кто-нибудь, пожалуйста, помочь мне понять значение символа ‘_’ в установщиках и геттерах javascript. Например, у меня есть следующий код, который работает нормально.

 var user = {
    get name() {
        return this._name;
    },    
    set name(value) {
        this._name = value;
    }
};

var me = user;
me.name = "Rob";

alert(me.name);
  

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

 var user = {
    get name() {
        return this.name;
    },    
    set name(value) {
        this.name = value;
    }
};

var me = user;
me.name = "Rob";

alert(me.name);

</script>
  

Может кто-нибудь, пожалуйста, объяснить мне, что «_» делает в этой ситуации?

Комментарии:

1. _name ( с подчеркиванием) является закрытым для вашего user объекта, но name ( без подчеркивания) является общедоступным и изменяемым из внешней области. итак, по сути, вы вызываете name извне, который затем снова вызывает себя и, следовательно, становится рекурсивным.

2. в js нет частных / общедоступных свойств, это просто конфликт имен. вам нужен параметр состояния отдельно от вашего свойства access для геттеров.

Ответ №1:

Это довольно просто. В вашем втором примере, get , вызывает себя.

Поскольку вы ссылаетесь на свойство me.name , JavaScript нуждается в get этом свойстве. Когда это происходит, запускается геттер. Используя ваш второй пример, JavaScript вызывает средство получения, но затем ему предлагается сделать то же самое: получить свойство, для обработки которого оно предназначено. Функция всегда вызывает саму себя, что делает ее бесконечно рекурсивной.

Однако в первом примере свойство, которое извлекается в получателе, не совпадает с тем, которое первоначально запустило получатель. Значение, получаемое получателем, является своего рода компонентом хранилища, чтобы избежать проблемы рекурсии, упомянутой выше. Два свойства не имеют фактической связи между ними, даже если они имеют похожие имена.

Та же идея применима и к сеттеру.

Комментарии:

1. Вопрос — является ли это соглашением в js, что любое свойство, управляемое с помощью getter / setter, должно быть добавлено с подчеркиванием?

2. @AnkurMarwaha Иногда используется для частных полей, которые таковыми и являются. Ответ Анибе Агамы говорит об этом подробнее.

3. Допустим, у меня есть свойство this.name , и я пытаюсь получить к нему доступ с get name помощью this.name , тогда происходит рекурсия, это понятно. Но, сделав только одно изменение внутри get name , т.е. Используя this._name его, все работает нормально. Итак, похоже, что js добавил что-то внутренне для идентификации свойства _ с помощью обычного имени свойства. Это то, в чем я все еще не уверен.

4. @AnkurMarwaha Используя _name вместо name , вы используете совершенно другую переменную. Вы можете использовать любое другое имя переменной, кроме name . При использовании name JavaScript необходимо вызвать его getter , который является текущей функцией, что вызывает бесконечную рекурсию. Это то же самое, что и это: function getname() {return getname()} . Если вы используете _name which не имеет getter , вы просто получаете значение.

5. Спасибо за ваше терпение, чувак, ты потрясающий. Я понял, что совершаю какую-то глупую ошибку.

Ответ №2:

Это соглашение об именовании, используемое для идентификации частных переменных или свойств. Это _ не имеет особого значения для JS.

Из руководства по стилю JavaScript Airbnb:

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

https://github.com/airbnb/javascript#22.4