Методы в объектах ES6: использование стрелочных функций

96

В ES6 оба они допустимы:

var chopper = {
    owner: 'Zed',
    getOwner: function() { return this.owner; }
};

и, как сокращение:

var chopper = {
    owner: 'Zed',
    getOwner() { return this.owner; }
}

Можно ли также использовать новые стрелочные функции? Пытаясь что-то вроде

var chopper = {
    owner: 'John',
    getOwner: () => { return this.owner; }
};

или

var chopper = {
    owner: 'John',
    getOwner: () => (this.owner)
};

Я получаю сообщение об ошибке, предполагающее, что у метода нет доступа к this. Это просто проблема синтаксиса, или вы не можете использовать методы толстой трубы внутри объектов ES6?

лиса
источник
11
Одним из главных достоинств нового синтаксиса функции было то, что он работает по- thisдругому. Он определяется лексической средой, в которой была создана функция, что означает, что thisзначение, в котором вы создаете chopperпеременную, будет thisзначением функции. Другими словами, он не будет ссылаться на chopperобъект.
1
При использовании синтаксиса толстой стрелки? Только если вы измените thisзначение, сначала создав chopperобъект, а затем выполняя присвоение в функции, thisуказывающей на этот объект. Это можно сделать довольно чисто с помощью функции-конструктора.
1
Эта демонстрация будет работать в Firefox. В Chrome его еще нет. jsfiddle.net/bfyarxfe
2
@fox, для этого jsfiddle вы должны использовать "use strict".
Уолтер Чапилликен - wZVanG
1
@fox: отлично работает в поддерживаемой среде. Firefox пока не имеет полной поддержки. Попробуйте в Continuum и console.log()результат вызова метода. Оно работает.

Ответы:

154

Стрелочные функции не предназначены для использования в каждой ситуации просто как сокращенная версия устаревших функций. Они не предназначены для замены синтаксиса функции с использованием functionключевого слова. Наиболее распространенный вариант использования стрелочных функций - это короткие «лямбды», которые не переопределяются this, часто используемые при передаче функции в качестве обратного вызова какой-либо функции.

Стрелочные функции нельзя использовать для написания методов объекта, потому что, как вы обнаружили, поскольку стрелочные функции закрывают thisлексически охватывающий контекст, thisвнутри стрелки является тот, который был текущим в том месте, где вы определили объект. То есть:

// Whatever `this` is here...
var chopper = {
    owner: 'Zed',
    getOwner: () => {
        return this.owner;    // ...is what `this` is here.
    }
};

В вашем случае, желая написать метод для объекта, вы должны просто использовать традиционный functionсинтаксис или синтаксис метода, представленный в ES6:

var chopper = {
    owner: 'Zed',
    getOwner: function() {
        return this.owner;
    }
};

// or

var chopper = {
    owner: 'Zed',
    getOwner() {
        return this.owner;
    }
};

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

В списке рассылки es6 велись споры об изменении стрелочных функций, которые имеют похожий синтаксис, но со своим собственным this. Однако это предложение было плохо воспринято, потому что это просто синтаксический сахар, позволяющий сэкономить при вводе нескольких символов и не предоставляющий новых функциональных возможностей по сравнению с существующим синтаксисом функций. См. Тему несвязанные стрелочные функции .

TJ Crowder
источник
Если я правильно это читаю, это наводит на мысль, что список рассылки лишает синтаксического сахара приоритета, даже если это приведет к большей единообразию / читаемости кода. В нынешнем виде гораздо сложнее использовать функции жирной стрелки в контексте ООП в ES6, чем, скажем, в coffeescript.
fox
Как я понимаю, синтаксический сахар будет считаться уважительной причиной для рассмотрения расширений языка, но , как вы говорите с более низким приоритетом , - другими словами, бар выше для таких предложений.
12

В этой строке getOwner: => (this.owner)должно быть:

var chopper = {
    owner: 'John',
    getOwner: () => this.owner
}; //here `this` refers to `window` object.

Вам нужно будет объявить thisфункцию:

var chopper = {
    owner: 'John',
    getOwner() { return this.owner }
};

Или:

var chopperFn = function(){

    this.setOwner = (name) => this.owner = name;
    Object.assign(this,{
        owner: 'Jhon',
        getOwner: () => this.owner,
    })

}

var chopper = new chopperFn();
console.log(chopper.getOwner());
chopper.setOwner('Spiderman');
console.log(chopper.getOwner());

Уолтер Чапилликен - wZVanG
источник
1
Я получаю сообщение об ошибке:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox
Я вижу, это правильное использование, однако метод esta всегда возвращает объект окна. Вам нужно будет объявить thisвнутри функции.
Уолтер Чапилликен - wZVanG
2
thisне обязательно относится к window. Он относится к тому, что текущее значение thisнаходится в окружающей среде, которая может быть или не быть window. Может ты это имел в виду. Просто хочу убедиться, что он понимает, что это не какое-то значение по умолчанию.
@torazaburo Это нормально для меня, я попробовал, thisтеперь относится к классу
Уолтер Чапилликен - wZVanG
2
То, что вы написали, эквивалентно простому письму, но более подробное var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.
1

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

  • Используйте функции без стрелок для методов, которые будут использовать object.method()синтаксис. (Это функции, которые получат значимое thisзначение от вызывающего.)
  • Используйте функцию стрелки почти для всего остального.
Исуру Мальдения
источник
0

Эта внутренняя стрелочная функция не отражает контекст объекта. Вместо этого он дает контекст, в котором вызывается метод объекта.

Отметьте это, это дает некоторое представление о том, когда использовать стрелку, а когда нет. https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/

прабушитха
источник
0

Если вам нужно использовать функцию стрелки, вы можете изменить thisна chopper,

var chopper = {
  owner: "John",
  getOwner: () => chopper.owner
};

Хотя это не лучшая практика, при изменении имени объекта необходимо изменить эту стрелочную функцию.

фоксирис
источник
0

Другой совет, в строгом режиме, по- thisпрежнему относится к Window, а не к undefined.

  (() => {
    "use strict";
    console.log(this); // window
  })();

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Вимники Луо
источник