Métodos em objetos ES6: usando funções de seta


97

No ES6, ambos são legais:

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

e, como abreviação:

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

É possível usar as novas funções de seta também? Em tentar algo como

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

ou

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

Recebo mensagens de erro sugerindo que o método não tem acesso a this. Isso é apenas um problema de sintaxe ou você não pode usar métodos fat-pipe dentro de objetos ES6?


11
Um dos maiores pontos da nova sintaxe da função é que ela trata de maneira thisdiferente. É definido pelo ambiente léxico no qual a função foi criada, o que significa que o thisvalor onde você cria a choppervariável será o thisvalor da função. Em outras palavras, não fará referência ao chopperobjeto.

1
Ao usar a sintaxe de seta grande? Somente se você alterar o thisvalor criando primeiro o chopperobjeto e, em seguida, fazendo a atribuição em uma função que thisaponta para aquele objeto. Isso pode ser feito de forma bastante limpa com uma função de construtor.

1
Esta demonstração será executada no Firefox. O Chrome ainda não tem. jsfiddle.net/bfyarxfe

2
@fox, você deve usar 'use strict' nesse jsfiddle.
Walter Chapilliquen - wZVanG 28/06/2015

1
@fox: Funciona bem em um ambiente compatível. O Firefox ainda não tem suporte completo. Experimente no Continuum e console.log()o resultado da chamada do método. Funciona.

Respostas:


158

As funções de seta não foram projetadas para serem usadas em todas as situações, apenas como uma versão mais curta das funções antigas. Eles não pretendem substituir a sintaxe da função usando a functionpalavra - chave. O caso de uso mais comum para funções de seta é como "lambdas" curtos que não redefinem this, geralmente usados ​​ao passar uma função como retorno de chamada para alguma função.

As funções de seta não podem ser usadas para escrever métodos de objeto porque, como você descobriu, uma vez que as funções de seta se fecham sobre o thiscontexto de inclusão lexical, o thisdentro da seta é aquele que estava atual onde você definiu o objeto. O que quer dizer:

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

No seu caso, querendo escrever um método em um objeto, você deve simplesmente usar a functionsintaxe tradicional ou a sintaxe do método introduzida no ES6:

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

// or

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

(Existem pequenas diferenças entre eles, mas só são importantes se você usar superem getOwner, o que não é ou se copiar getOwnerpara outro objeto.)

Houve algum debate na lista de discussão es6 sobre uma variação nas funções de seta que têm sintaxe semelhante, mas com a sua própria this. No entanto, essa proposta foi mal recebida porque é um mero açúcar de sintaxe, permitindo que as pessoas economizem ao digitar alguns caracteres e não fornece nenhuma funcionalidade nova sobre a sintaxe de função existente. Consulte o tópico funções de setas não acopladas .


Se estou lendo corretamente, parece sugerir que a lista de discussão desprioriza o açúcar sintático, mesmo que isso leve a uma maior uniformidade / legibilidade do código. Do jeito que está, é muito mais desafiador usar as funções seta gorda em um contexto OOP em ES6 do que, digamos, em coffeescript.
fox

Pelo que entendi, o açúcar sintático é considerado um motivo válido para considerar extensões de linguagem, mas como você disse com uma prioridade menor - em outras palavras, a barra é maior para tais propostas.

12

Nesta linha getOwner: => (this.owner)deve estar:

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

Você teria que declarar thisem uma função:

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


1
Estou recebendo um erro aqui:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox

Entendo, é o uso correto, porém o método esta sempre retorna a janela Object. Você teria que declarar thisdentro de uma função.
Walter Chapilliquen - wZVanG

2
thisnão necessariamente se refere a window. Refere-se a qualquer que seja o valor atual de thisno ambiente envolvente, que pode ou não ser window. Talvez seja isso que você quis dizer. Só quero ter certeza de que ele entendeu que não é um valor padrão.

@torazaburo Para mim tudo bem, experimentei, thisagora refere-se à classe
Walter Chapilliquen - wZVanG 28/06/2015

2
O que você escreveu é equivalente, mas mais detalhado do que simplesmente escrever var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.

1

Uma dica rápida que sigo para usar as funções de seta.

  • Use funções que não sejam setas para métodos que usarão object.method() sintaxe. (Essas são funções que receberãothis valor de seu chamador.)
  • Use a função de seta para quase tudo o mais.


0

Se você tiver que usar a função de seta, você pode mudar thispara chopper,

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

Embora esta não seja a melhor prática, ao alterar o nome do objeto, você deve alterar esta função de seta.


0

Outra dica, no modo estrito, thisainda se refere à janela em vez de indefinida.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.