Методи в об'єктах 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 ви повинні використовувати `` використовувати строго ''.
Walter Chapilliquen - wZVanG

1
@fox: Він чудово працює в підтримуваному середовищі. Firefox ще не має повної підтримки. Спробуйте в Continuum та console.log()результат виклику методу. Це працює.

Відповіді:


155

Функції зі стрілками не призначені для використання у будь-якій ситуації лише як коротша версія старомодних функцій. Вони не призначені для заміни синтаксису функції за допомогою 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;
    }
};

(Є невеликі відмінності між ними, але вони тільки важливо , якщо ви використовуєте superв getOwner, яких у вас немає, або якщо скопіювати getOwnerна інший об'єкт.)

У списку розсилки es6 було деяке обговорення щодо повороту на функціях стрілок, які мають подібний синтаксис, але зі своїм власним this. Однак ця пропозиція була сприйнята погано, оскільки це лише синтаксис цукру, що дозволяє людям економити введення декількох символів і не надає нових функціональних можливостей щодо існуючого синтаксису функцій. Див. Розділ функції розв’язаних стрілок .


Якщо я читаю це правильно, схоже, припускає, що список розсилки деприорідізує синтаксичний цукор, навіть якщо це призведе до більшої однорідності / читабельності коду. На даний момент набагато складніше використовувати функції стрілки жиру в контексті ООП під ES6, ніж, скажімо, під coffeescript.
лисиця

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

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());


1
Я отримую тут помилку:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox

Я бачу, це правильне використання, однак метод esta завжди повертає вікно Object. Вам потрібно було б оголосити thisвсередині функції.
Walter Chapilliquen - 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

Якщо вам потрібно використовувати функцію стрілки, ви можете змінити thisна chopper,

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

Хоча це не найкраща практика, коли ви змінюєте назву об’єкта, вам потрібно змінити цю функцію стрілки.


0

Ще одна порада, у строгому режимі, thisяк і раніше посилається на Вікно, а не на невизначений.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.