Méthodes dans les objets ES6: utilisation des fonctions fléchées

96

Dans ES6, les deux sont légaux:

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

et, en sténographie:

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

Est-il possible d'utiliser également les nouvelles fonctions fléchées? En essayant quelque chose comme

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

ou

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

Je reçois un message d'erreur suggérant que la méthode n'a pas accès à this. S'agit-il simplement d'un problème de syntaxe ou ne pouvez-vous pas utiliser de méthodes fat-pipe à l'intérieur des objets ES6?

Renard
la source
11
L'un des principaux points de la nouvelle syntaxe de fonction était qu'elle traite thisdifféremment. Il est défini par l'environnement lexical dans lequel la fonction a été créée, ce qui signifie que la thisvaleur où vous créez la choppervariable sera la thisvaleur de la fonction. En d'autres termes, il ne fera pas référence à l' chopperobjet.
1
En utilisant la syntaxe de la grosse flèche? Uniquement si vous modifiez la thisvaleur en créant d'abord l' chopperobjet, puis en effectuant l'affectation dans une fonction qui thispointe vers cet objet. Cela peut être accompli assez proprement avec une fonction constructeur.
1
Cette démo fonctionnera dans Firefox. Chrome ne l'a pas encore. jsfiddle.net/bfyarxfe
2
@fox, vous devez utiliser 'use strict' sur ce jsfiddle.
Walter Chapilliquen - wZVanG
1
@fox: Cela fonctionne bien dans un environnement pris en charge. Firefox n'a pas encore de support complet. Essayez-le dans Continuum et console.log()le résultat de l'appel de méthode. Ça marche.

Réponses:

154

Les fonctions fléchées ne sont pas conçues pour être utilisées dans toutes les situations simplement comme une version abrégée de fonctions à l'ancienne. Ils ne visent pas à remplacer la syntaxe de fonction à l'aide du functionmot - clé. Le cas d'utilisation le plus courant pour les fonctions fléchées est celui des "lambdas" courts qui ne se redéfinissent pas this, souvent utilisés lors du passage d'une fonction en tant que rappel à une fonction.

Les fonctions fléchées ne peuvent pas être utilisées pour écrire des méthodes d'objet car, comme vous l'avez constaté, puisque les fonctions fléchées se ferment sur le thiscontexte englobant lexicalement, thisla flèche à l' intérieur de la flèche est celle qui était courante là où vous avez défini l'objet. C'est-à-dire:

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

Dans votre cas, voulant écrire une méthode sur un objet, vous devez simplement utiliser la functionsyntaxe traditionnelle , ou la syntaxe de méthode introduite dans ES6:

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

// or

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

(Il existe de petites différences entre eux, mais elles ne sont importantes que si vous utilisez superin getOwner, ce que vous n'êtes pas, ou si vous copiezgetOwner dans un autre objet.)

Il y a eu un débat sur la liste de diffusion es6 à propos d'une torsion des fonctions fléchées qui ont une syntaxe similaire mais avec la leur this. Cependant, cette proposition a été mal accueillie car il ne s'agit que d'un simple sucre de syntaxe, permettant aux gens d'économiser quelques caractères et ne fournit aucune nouvelle fonctionnalité par rapport à la syntaxe de fonction existante. Consultez la rubrique Fonctions fléchées indépendantes .

TJ Crowder
la source
Si je lis ceci correctement, cela semble suggérer que la liste de diffusion dépriorise le sucre syntaxique, même si cela conduirait à une plus grande uniformité / lisibilité du code. Dans l'état actuel des choses, il est beaucoup plus difficile d'utiliser les fonctions de grosse flèche dans un contexte POO sous ES6 que, par exemple, sous coffeescript.
fox
Si je comprends bien, le sucre syntaxique est considéré comme une raison valable pour envisager des extensions de langage, mais comme vous le dites avec une priorité moindre - en d’autres termes, la barre est plus élevée pour de telles propositions.
12

Dans cette ligne getOwner: => (this.owner)devrait être:

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

Vous devrez déclarer thisdans une fonction:

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

Ou:

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

Walter Chapilliquen - wZVanG
la source
1
Je reçois une erreur ici:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox
Je vois, c'est l'utilisation correcte, cependant la méthode esta renvoie toujours window Object. Vous devrez déclarer thisdans une fonction.
Walter Chapilliquen - wZVanG
2
thisne fait pas nécessairement référence à window. Il fait référence à la valeur actuelle de thisdans l'environnement englobant, qui peut ou non être window. C'est peut-être ce que vous vouliez dire. Je veux juste m'assurer qu'il comprend qu'il ne s'agit pas d'une valeur par défaut.
@torazaburo C'est bien pour moi, je l'ai essayé, thisfait maintenant référence à la classe
Walter Chapilliquen - wZVanG
2
Ce que vous avez écrit équivaut, mais plus verbeux, à la simple écriture var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.
1

Un petit conseil que je suis pour utiliser les fonctions fléchées.

  • Utilisez des fonctions non fléchées pour les méthodes qui utiliseront la object.method()syntaxe. (Ce sont des fonctions qui recevront une thisvaleur significative de leur appelant.)
  • Utilisez la fonction fléchée pour presque tout le reste.
Isuru Maldeniya
la source
0

Si vous devez utiliser la fonction flèche, vous pouvez passer thisà chopper,

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

Bien que ce ne soit pas la meilleure pratique, lorsque vous modifiez le nom de l'objet, vous devez modifier cette fonction de flèche.

Foxiris
la source
0

Une autre astuce, en mode strict, thisfait toujours référence à Window au lieu d'indéfini.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Vimniky Luo
la source