Metodi negli oggetti ES6: utilizzo delle funzioni freccia


96

In ES6, entrambi sono legali:

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

e, come abbreviazione:

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

È possibile utilizzare anche le nuove funzioni freccia? Nel provare qualcosa di simile

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

o

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

Ricevo un messaggio di errore che suggerisce che il metodo non ha accesso a this. È solo un problema di sintassi o non è possibile utilizzare metodi fat-pipe all'interno degli oggetti ES6?


11
Uno dei punti più importanti della nuova sintassi della funzione era che tratta in modo thisdiverso. È definito dall'ambiente lessicale in cui è stata creata la funzione, il che significa che il thisvalore in cui crei la choppervariabile sarà il thisvalore della funzione. In altre parole, non farà riferimento chopperall'oggetto.

1
Durante l'utilizzo della sintassi della freccia grassa? Solo se modifichi il thisvalore creando prima l' chopperoggetto, quindi eseguendo l'assegnazione in una funzione che thispunta a quell'oggetto. Questo può essere ottenuto in modo abbastanza pulito con una funzione di costruzione.

1
Questa demo verrà eseguita in Firefox. Chrome non ce l'ha ancora. jsfiddle.net/bfyarxfe

2
@fox, devi usare "use strict" su quel jsfiddle.
Walter Chapilliquen - wZVanG

1
@fox: funziona bene in un ambiente supportato. Firefox non ha ancora un supporto completo. Provalo in Continuum e console.log()il risultato della chiamata al metodo. Funziona.

Risposte:


154

Le funzioni freccia non sono progettate per essere utilizzate in ogni situazione semplicemente come una versione più breve di funzioni antiquate. Non intendono sostituire la sintassi della funzione utilizzando la functionparola chiave. Il caso d'uso più comune per le funzioni freccia è costituito da brevi "lambda" che non vengono ridefiniti this, spesso utilizzati quando si passa una funzione come callback a qualche funzione.

Le funzioni freccia non possono essere utilizzate per scrivere metodi oggetto perché, come hai scoperto, poiché le funzioni freccia si chiudono sul thiscontesto lessicale che lo racchiude, l' thisinterno della freccia è quello corrente nel punto in cui hai definito l'oggetto. Vale a dire:

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

Nel tuo caso, volendo scrivere un metodo su un oggetto, dovresti semplicemente usare la functionsintassi tradizionale , o la sintassi del metodo introdotta in ES6:

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

// or

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

(Ci sono piccole differenze tra loro, ma sono importanti solo se usi superin getOwner, cosa che non sei o se copi getOwnersu un altro oggetto.)

C'è stato un dibattito sulla mailing list es6 su una svolta nelle funzioni freccia che hanno una sintassi simile ma con la propria this. Tuttavia, questa proposta è stata accolta male perché si tratta di un semplice zucchero sintattico, che consente alle persone di risparmiare digitando alcuni caratteri e non fornisce nuove funzionalità rispetto alla sintassi delle funzioni esistenti. Vedere l'argomento Funzioni delle frecce non associate .


Se sto leggendo questo correttamente, sembra suggerire che la mailing list deprezza lo zucchero sintattico, anche se porterebbe a una maggiore uniformità / leggibilità del codice. Allo stato attuale, è molto più difficile utilizzare le funzioni fat-arrow in un contesto OOP sotto ES6 che, diciamo, sotto coffeescript.
volpe

A quanto ho capito, lo zucchero sintattico è considerato un motivo valido per considerare le estensioni linguistiche, ma come dici tu con una priorità inferiore - in altre parole, la barra è più alta per tali proposte.

12

In questa riga getOwner: => (this.owner)dovrebbe essere:

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

Dovresti dichiarare thisin una funzione:

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

O:

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
Ricevo un errore qui:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
volpe

Capisco, è l'uso corretto, tuttavia il metodo esta restituisce sempre Window Object. Dovresti dichiarare thisall'interno di una funzione.
Walter Chapilliquen - wZVanG

2
thisnon si riferisce necessariamente a window. Si riferisce a qualunque sia il valore corrente di thisè nell'ambiente circostante, che può essere o meno window. Forse è questo che intendevi. Voglio solo assicurarti che capisca che non è un valore predefinito.

@torazaburo Per me va bene, l'ho provato, thisora si riferisce alla classe
Walter Chapilliquen - wZVanG

2
Ciò che hai scritto equivale a, ma è più dettagliato della semplice scrittura var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.

1

Un rapido suggerimento che seguo per utilizzare le funzioni freccia.

  • Usa funzioni non freccia per i metodi che useranno la object.method()sintassi. (Queste sono funzioni che riceveranno un thisvalore significativo dal loro chiamante.)
  • Usa la funzione freccia per quasi tutto il resto.


0

Se devi usare la funzione freccia, puoi passare thisa chopper,

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

Sebbene questa non sia una procedura ottimale, quando si modifica il nome dell'oggetto, è necessario modificare questa funzione della freccia.


0

Un altro suggerimento, in modalità rigorosa, thissi riferisce ancora a Window invece che a undefined.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.