Геттер / сеттер ES6 с функцией стрелки

106

Я использую babel6 и для своего любимого проекта создаю оболочку для XMLHttpRequest для методов, которые я могу использовать:

open = (method, url, something) => {
  return this.xhr.open(method, url, something);
}

но для свойств стрелочная функция не работает

это работает:

get status() { return this.xhr.status; }

но я не могу использовать

get status = () => this.xhr.status;

Это намеренно?

Габор Долла
источник
Вам не нужны фигурные скобки или возврат; можно просто сказать (method, url, something) => this.xhr.open(method. url, something).
getявляется частью литерала объекта или определения класса, а присвоение переменной - нет. Как вы думаете, почему они должны работать одинаково?
Bergi
2
status => this.xhr.status( get status() => this.xhr.statusсинтаксис c # 7) или, может быть , действительно был бы отличным синтаксическим сахаром для удобочитаемости, но Javascript not Typescript (пока?) не поддерживает его
Чарльз ХЕТЬЕР

Ответы:

113

Согласно грамматике ES2015, свойство литерала объекта может быть только одним из четырех:

Свойство Определение :

  • IdentifierReference
  • PropertyName : AssignmentExpression
  • Метод Определение

Единственный из этих типов, который допускает ведущие, get- это MethodDefinition :

Метод Определение :

  • PropertyName ( StrictFormalParameters ) { FunctionBody }
  • ГенераторМетод
  • get PropertyName ( ) { FunctionBody }
  • set Имя свойства ( PropertySetParameterList ) { FunctionBody }

Как видите, getформа следует очень ограниченной грамматике, которая должна иметь вид

get NAME () { BODY }

Грамматика не допускает функций формы get NAME = ....

апсиллер
источник
Спасибо за помощь, я принимаю ваш ответ. Вы знаете, где определено, что геттер / сеттер нельзя использовать с присваиванием? Просто любопытно.
Габор Долла
@GaborDolla Отредактировано для ссылки на грамматику объектных литералов в спецификации ECMAScript.
apsillers
39

Принятый ответ великолепен. Лучше всего, если вы хотите использовать обычный синтаксис функции вместо компактного «синтаксиса стрелочной функции».

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

Например, я заметил использование OP this, вы можете захотеть выполнить лексическое связывание this; aka «не привязка этого» ), и стрелочные функции хороши для этой лексической привязки.

Вы все еще можете использовать стрелочную функцию с геттером через эту Object.definePropertyтехнику.

{
  ...
  Object.defineProperty(your_obj, 'status', { 
     get : () => this.xhr.status 
  });
  ...
}

См. Упоминания object initializationтехники (ака get NAME() {...}) и definePropertyтехники (ака get : ()=>{}) . Есть по крайней мере одно существенное отличие: для использования definePropertyтребуются переменные, которые уже существуют:

Определение геттера для существующих объектов

то есть с Object.definePropertyвы должны убедиться, что your_obj(в моем примере) существует и сохраняется в переменной (тогда как с помощью object-initializationвы можете вернуть объектный литерал при инициализации вашего объекта :) {..., get(){ }, ... }. Более подробная информация Object.definePropertyздесь

Object.defineProperty(...)похоже, имеет сопоставимую поддержку браузера с get NAME(){...}синтаксисом; современные браузеры, IE 9.

Красный горошек
источник
11
Умно, но в конечном итоге гораздо более подробный, чем просто:get status() { return this.xhr.status; }
devuxer
2
@devuxer Я согласен, это слишком многословно. Но для ясности: ваш this должен быть объектом, в котором ваш get status() { ... }определяется. Но my this может быть чем-то другим из-за различий в лексической привязке, верно?
The Red Pea
2
Согласитесь ... хотя на практике я не сталкивался со случаем, когда thisне то, что мне нужно, в аксессуаре get. (Преимущества thisпривязки стрелочных функций, кажется,
проявляются
3
Я согласен, я часто использую жирную стрелку + лексические привязки ()=>{}для обратных вызовов, которые я передаю в Promise , например $http(...).then((promise_result)=> this...})). Если я не использую жирную стрелку, thisбудет представлять глобальный Windowобъект; не очень полезно. Но я редко (никогда?) Использовал ()=>{}в качестве функции для "получить аксессор", как вы говорите ... по крайней мере, thisвнутри get()будет представлять объект, для которого get()определен (что уже более полезно, чем Window; поэтому нет необходимости использовать функция жирной стрелки!)
The Red Pea
1
definePropertyПодход полезен в петлях. Прямо сейчас я просто использовал его, чтобы показать некоторые свойства объекта chiled из содержащего.
Эдурне Паскуаль