Métodos en objetos ES6: uso de funciones de flecha


96

En ES6, ambos son legales:

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

y, como taquigrafía:

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

¿Es posible utilizar también las nuevas funciones de flecha? Al intentar algo como

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

o

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

Recibo un mensaje de error que sugiere que el método no tiene acceso a this. ¿Es esto solo un problema de sintaxis, o no puede usar métodos fat-pipe dentro de los objetos ES6?


11
Uno de los puntos más importantes de la sintaxis de la nueva función es que trata de manera thisdiferente. Está definido por el entorno léxico en el que se creó la función, lo que significa que el thisvalor donde crea la choppervariable será el thisvalor de la función. En otras palabras, no hará referencia al chopperobjeto.

1
¿Mientras usa la sintaxis de la flecha gruesa? Solo si altera el thisvalor creando primero el chopperobjeto y luego haciendo la asignación en una función que thisapunte a ese objeto. Esto se puede lograr de forma bastante limpia con una función de constructor.

1
Esta demostración se ejecutará en Firefox. Chrome aún no lo tiene. jsfiddle.net/bfyarxfe

2
@fox, debe usar 'use estricto' en ese jsfiddle.
Walter Chapilliquen - wZVanG

1
@fox: funciona bien en un entorno compatible. Firefox aún no tiene soporte completo. Pruébelo en Continuum y console.log()el resultado de la llamada al método. Funciona.

Respuestas:


154

Las funciones de flecha no están diseñadas para usarse en todas las situaciones simplemente como una versión más corta de funciones pasadas de moda. No pretenden reemplazar la sintaxis de la función utilizando la functionpalabra clave. El caso de uso más común para las funciones de flecha es tan corto como "lambdas" que no redefinenthis , a menudo se utilizan cuando se pasa una función como una devolución de llamada a alguna función.

Las funciones de flecha no se pueden usar para escribir métodos de objeto porque, como ha encontrado, dado que las funciones de flecha se cierran sobre el thiscontexto que las encierra léxicamente, el thisinterior de la flecha es el que estaba vigente donde definió el objeto. Que es decir:

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

En su caso, si desea escribir un método en un objeto, simplemente debe usar la functionsintaxis tradicional o la sintaxis del método introducida en ES6:

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

// or

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

(Hay pequeñas diferencias entre ellos, pero solo son importantes si usa superin getOwner, que no es, o si copia getOwnera otro objeto).

Hubo cierto debate en la lista de correo de es6 sobre un giro en las funciones de flecha que tienen una sintaxis similar pero con la suya propia this. Sin embargo, esta propuesta fue mal recibida porque es un simple azúcar sintáctico, lo que permite a las personas ahorrar escribiendo algunos caracteres y no proporciona una nueva funcionalidad sobre la sintaxis de funciones existente. Consulte el tema Funciones de flechas independientes .


Si estoy leyendo esto correctamente, parece sugerir que la lista de correo desprioriza el azúcar sintáctico, incluso si daría lugar a una mayor uniformidad / legibilidad del código. En su forma actual, es mucho más desafiante usar las funciones fat-arrow en un contexto OOP bajo ES6 que, digamos, bajo coffeescript.
zorro

Según tengo entendido, el azúcar sintáctico se considera una razón válida para considerar las extensiones de idioma, pero como usted dice con una prioridad más baja, en otras palabras, el listón es más alto para tales propuestas.

12

En esta línea getOwner: => (this.owner)debería estar:

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

Tendrías que declarar thisen una función:

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
Recibo un error aquí:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox

Ya veo, es el uso correcto, sin embargo el método esta siempre devuelve window Object. Tendría que declarar thisdentro de una función.
Walter Chapilliquen - wZVanG

2
thisno necesariamente se refiere a window. Se refiere a cualquier valor actual de que se thisencuentre en el entorno circundante, que puede estar o no window. Quizás eso es lo que quisiste decir. Solo quiero asegurarme de que entiende que no es un valor predeterminado.

@torazaburo Eso está bien para mí, lo probé, thisahora se refiere a clase
Walter Chapilliquen - wZVanG

2
Lo que ha escrito es equivalente a, pero más detallado, que simplemente escribir var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.

1

Un consejo rápido que sigo para usar las funciones de flecha.

  • Use funciones que no sean flechas para métodos que usarán object.method()sintaxis. (Esas son funciones que recibirán un thisvalor significativo de su interlocutor).
  • Utilice la función de flecha para casi todo lo demás.


0

Si tiene que utilizar la función de flecha, puede cambiar thisa chopper,

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

Aunque esta no es la mejor práctica, cuando cambia el nombre del objeto, debe cambiar esta función de flecha.


0

Otro consejo, en modo estricto, thistodavía se refiere a Window en lugar de undefined.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.