2015-09-12 15 views
36

Mi sembra che, in ES6, le seguenti due funzioni sono molto quasi identica:Quali sono le differenze (se presenti) tra le funzioni freccia ES6 e le funzioni associate a Function.prototype.bind?

function() { 
    return this; 
}.bind(this); 

() => { 
    return this; 
}; 

Il risultato finale sembra lo stesso: funzioni freccia producono un oggetto funzione JavaScript con il loro this contesto legato alla lo stesso valore di this dove sono stati creati.

Ovviamente, in senso generale, Function.prototype.bind è più flessibile rispetto funzioni freccia: si può legare a valori diversi dal locale this, e può impegnare qualsiasi this in qualsiasi punto nel tempo funzione, potenzialmente molto tempo dopo che si crea inizialmente . Tuttavia, non sto chiedendo come lo stesso bind sia diverso dalle funzioni di freccia, sto chiedendo come le funzioni di freccia differiscono da immediatamente chiamando bind con this.

Esistono differenze tra i due costrutti in ES6?

+0

Con 'bind' si stanno essenzialmente creando due funzioni. Oltre a ciò, le cose che hai citato e il fatto che le funzioni delle frecce hanno una sintassi più concisa, non c'è differenza. –

+0

Poiché questa domanda non viene cercata e le sue risposte non offrono le occasioni in cui si potrebbe avere una buona ragione per usare 'bind' su una funzione a freccia, ho fatto una nuova domanda su quando farlo: https: // runkit. com/embed/yhv29j5sybvn – hippietrail

risposta

27

Non ci sono differenze (significative).

Bene, ok, è un po 'prematuro. Ci sono tre piccole differenze uniche per le funzioni di freccia.

  1. Le funzioni freccia non possono essere utilizzate con new.

    Ciò significa, ovviamente, che non hanno una proprietà prototype e non possono essere utilizzati per creare un oggetto con la sintassi di ispirazione classica.

    new (() => {}) // TypeError:() => {} is not a constructor 
    

    Questa è probabilmente la cosa migliore, anche se il modo in cui-new opere non avrebbero molto senso con le funzioni legate.

  2. Le funzioni di freccia non hanno accesso allo speciale oggetto arguments a cui le normali funzioni JavaScript hanno accesso.

    (() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined 
    

    Questo è probabilmente un po 'più di un trucchetto. Presumibilmente questo è quello di rimuovere una delle altre stranezze di JavaScript. The arguments object is its own special beast, e ha un comportamento strano, quindi non sorprende che sia stato lanciato.

    Invece, ES6 ha simboli che possono realizzare la stessa cosa senza alcuna variabile magia nascosta: funzioni

    ((...args) => args)(1, 2, 3) // [1, 2, 3] 
    
  3. freccia non hanno un proprio new.target proprietà, usare il new.target della loro funzione racchiude, se esiste.

    Questo è coerente con le altre modifiche per rimuovere "magicamente" i valori introdotti per le funzioni di freccia. Questo particolare cambiamento è particolarmente ovvio, considerando comunque che le funzioni di freccia non possono essere utilizzate con new, come menzionato sopra.

Altrimenti, le frecce sono come funzioni legate, semanticamente.È possibile che le frecce siano più performanti, dal momento che non devono portare con sé il bagaglio extra e dal momento che non devono essere prima convertite dalle normali funzioni, ma sono comportamentalmente esattamente uguali.

+2

Non direi che 'arguments' è stato gettato a causa di" comportamento strano "(che è comunque risolto in modalità rigorosa). Piuttosto, le funzioni a freccia possono accedere all'oggetto 'arguments' della loro funzione di inclusione, coerentemente con il modo in cui accedono al suo binding' this' e 'new.target'. – Bergi

+3

@Bergi Anche in modalità strict, 'arguments' è molto strano: non è ancora un array, quindi uno splat è ancora più utile e prevedibile. –

24

ci sono alcune differenze:

  • funzioni freccia non può essere costruita. Sebbene entrambe le funzioni freccia e le funzioni associate non abbiano una proprietà .prototype, la prima genera un'eccezione quando viene chiamata con new mentre quest'ultima ignora il valore associato e chiama la funzione di destinazione come costruttore (con gli argomenti associati parzialmente applicati, comunque) sulla nuova istanza.

    function F() {} 
    var f =() => {}, 
        boundF = F.bind({}); 
    console.log(new boundF(), new boundF instanceof F) // {}, true 
    console.log(new f) // TypeError 
    
  • funzioni Freccia hanno lessicale arguments, new.target e super così (non solo lessicale this). Una chiamata a una funzione a freccia non inizializza nessuno di questi, sono semplicemente ereditati dalla funzione in cui è stata definita la funzione freccia. In una funzione associata, si riferiscono semplicemente ai rispettivi valori della funzione obiettivo.

  • Le funzioni di freccia non associano effettivamente un valore this. Piuttosto, non ne hanno uno, e quando si utilizza this viene visualizzato come un nome di variabile nello scope lessicale. Ciò consente di definire una funzione pigramente freccia mentre this non è ancora disponibile:

    class X extends Object { 
        constructor() { 
         var f =() => this, // works 
          boundF = function(){ return this; }.bind(this); 
    //             ^^^^ ReferenceError 
         super(); // initialises `this` 
         console.log(f(), f() == this); // {}, true 
        } 
    } 
    new X; 
    
  • funzioni Freccia non possono essere funzioni di generatore (anche se possono tornare generatori). È possibile utilizzare .bind() su una funzione generatore, ma non è possibile esprimerlo utilizzando una funzione freccia.

2

Ecco un altro sottile differenza:

funzioni freccia possono restituire una funzione senza utilizzare la parola 'ritorno', omettendo il {} parentesi graffe dopo l'=> immediatamente.

var f=x=>x;   console.log(f(3)); // 3 
var g=x=>{x};   console.log(g(3)); // undefined 
var h=function(x){x}; console.log(h(3)); // undefined 
var i=x=>{a:1};  console.log(i(3)); // undefined 
var j=x=>({a:1});  console.log(j(3)); // {a:1} 
Problemi correlati