A pergunta é direcionada a pessoas que pensaram no estilo do código no contexto do próximo ECMAScript 6 (Harmony) e que já trabalharam com o idioma.
Com () => {}
e function () {}
estamos obtendo duas maneiras muito semelhantes de escrever funções no ES6. Em outros idiomas, as funções lambda geralmente se distinguem por serem anônimas, mas no ECMAScript qualquer função pode ser anônima. Cada um dos dois tipos possui domínios de uso exclusivos (ou seja, quando é this
necessário vincular explicitamente ou explicitamente não). Entre esses domínios, existe um grande número de casos em que qualquer notação funciona.
As funções de seta no ES6 têm pelo menos duas limitações:
- Não trabalhe com
new
e não pode ser usado ao criarprototype
- Corrigido o
this
limite do escopo na inicialização
Essas duas limitações à parte, as funções de seta poderiam substituir teoricamente as funções regulares em quase qualquer lugar. Qual é a abordagem correta para usá-los na prática? As funções de seta devem ser usadas, por exemplo:
- "em todos os lugares em que trabalham", ou seja, em todos os lugares uma função não precisa ser independente da
this
variável e não estamos criando um objeto. - apenas "em todos os lugares em que são necessários", ou seja, ouvintes de eventos, tempos limite, que precisam estar vinculados a um determinado escopo
- com funções 'curtas', mas não com funções 'longas'
- somente com funções que não contenham outra função de seta
O que estou procurando é uma diretriz para selecionar a notação de função apropriada na versão futura do ECMAScript. A diretriz precisará ser clara, para que possa ser ensinada aos desenvolvedores em uma equipe e ser consistente para que não exija constante refatoração para frente e para trás de uma notação de função para outra.
Fixed this bound to scope at initialisation
uma limitação?this
algo que você pode fazer com funções regulares, mas não com funções de seta.Fixed this bound to scope at initialisation
seja uma limitação. :) Dê uma olhada neste artigo: exploringjs.com/es6/ch_arrow-functions.htmlRespostas:
Há um tempo, nossa equipe migrou todo o seu código (um aplicativo AngularJS de tamanho médio) para o JavaScript compilado usando o
TraceurBabel . Agora estou usando a seguinte regra geral para funções no ES6 e além:function
no escopo global e paraObject.prototype
propriedades.class
para construtores de objetos.=>
qualquer outro lugar.Por que usar as funções de seta em quase todos os lugares?
thisObject
que a raiz. Se mesmo um único retorno de chamada de função padrão estiver misturado com várias funções de seta, é possível que o escopo fique confuso.function
imediatamente se destaca para definir o escopo. Um desenvolvedor sempre pode procurar a próximafunction
declaração mais alta para ver o quethisObject
é.Por que sempre usar funções regulares no escopo global ou no escopo do módulo?
thisObject
.window
objeto (escopo global) é melhor endereçado explicitamente.Object.prototype
definições vivem no escopo global (penseString.prototype.truncate
etc.) e geralmente têm que ser do tipo defunction
qualquer maneira. O uso consistentefunction
no escopo global ajuda a evitar erros.function foo(){}
queconst foo = () => {}
- em particular fora de outras chamadas de função. (2) O nome da função é exibido em rastreamentos de pilha. Embora seja tedioso nomear cada retorno de chamada interno, nomear todas as funções públicas é provavelmente uma boa idéia.Construtores de objetos
Tentar instanciar uma função de seta gera uma exceção:
Uma vantagem importante das funções sobre as funções de seta é, portanto, que as funções funcionam como construtores de objetos:
No entanto, a definição de classe de rascunho 2 ES Harmony funcionalmente idêntica é quase tão compacta:
Espero que o uso da notação anterior acabe sendo desencorajado. A notação de construtor de objetos ainda pode ser usada por alguns para fábricas simples de objetos anônimos, onde objetos são gerados programaticamente, mas não por muito mais.
Onde um construtor de objetos é necessário, deve-se considerar a conversão da função para a,
class
como mostrado acima. A sintaxe também funciona com funções / classes anônimas.Legibilidade das funções das setas
Provavelmente, o melhor argumento para aderir a funções regulares - dane-se a segurança do escopo - seria que as funções de seta são menos legíveis que as funções regulares. Se o seu código não estiver funcional em primeiro lugar, as funções de seta podem não parecer necessárias e, quando as funções de seta não são usadas de maneira consistente, elas ficam feias.
O ECMAScript mudou bastante desde que o ECMAScript 5.1 nos deu o funcional
Array.forEach
,Array.map
e todos esses recursos funcionais de programação que nos utilizam usam funções onde for-loops teriam sido usados antes. O JavaScript assíncrono decolou bastante. O ES6 também enviará umPromise
objeto, o que significa ainda mais funções anônimas. Não há como voltar atrás para a programação funcional. No JavaScript funcional, as funções de seta são preferíveis às funções regulares.Tomemos, por exemplo, este código (particularmente confuso) 3 :
O mesmo trecho de código com funções regulares:
Embora qualquer uma das funções de seta possa ser substituída por uma função padrão, haveria muito pouco a ganhar com isso. Qual versão é mais legível? Eu diria o primeiro.
Penso que a questão de usar funções de seta ou funções regulares se tornará menos relevante ao longo do tempo. A maioria das funções se tornará métodos de classe, que eliminam a
function
palavra - chave, ou se tornarão classes. As funções permanecerão em uso nas classes de correção através doObject.prototype
. Nesse meio tempo, sugiro reservar afunction
palavra - chave para qualquer coisa que realmente deva ser um método ou classe.Notas
extend
palavra - chave. Uma pequena diferença é que as declarações de classe são constantes, enquanto as de função não.fonte
function
é quando você não querthis
ser vinculado, certo? Meu cenário mais comum para isso é eventos, nos quais você podethis
se referir ao objeto (geralmente nó DOM) que acionou o evento.=>
acaba ficando melhor com o tempo. Duvido que os não programadores se sentiriam muito diferentes sobre os dois exemplos. Se você estiver escrevendo o código ES2016, normalmente não usará muitas dessas funções de seta. Neste exemplo, usando async / waitit e uma compreensão de matriz, você acabaria com apenas uma função de seta nareduce()
chamada.De acordo com a proposta , as flechas tinham como objetivo "abordar e resolver vários pontos problemáticos comuns dos tradicionais
Function Expression
". Eles pretendiam melhorar as coisas ligando-sethis
lexicamente e oferecendo sintaxe concisa.Contudo,
this
lexicamentePortanto, as funções de seta criam oportunidades de confusão e erros e devem ser excluídas do vocabulário de um programador JavaScript, substituídas por
function
exclusivamente.Em relação ao léxico
this
this
é problemático:As funções de seta pretendem corrigir o problema em que precisamos acessar uma propriedade
this
dentro de um retorno de chamada. Já existem várias maneiras de fazer isso: Pode-se atribuirthis
a uma variável, usarbind
ou usar o terceiro argumento disponível nosArray
métodos agregados. No entanto, as setas parecem ser a solução mais simples, portanto o método pode ser refatorado da seguinte maneira:No entanto, considere se o código usou uma biblioteca como jQuery, cujos métodos se ligam
this
especialmente. Agora, existem doisthis
valores para lidar:Devemos usar
function
paraeach
poder ligarthis
dinamicamente. Não podemos usar uma função de seta aqui.Lidar com vários
this
valores também pode ser confuso, porque é difícil saber sobre o quethis
um autor estava falando:O autor realmente pretendeu telefonar
Book.prototype.reformat
? Ou ele esqueceu de ligarthis
e pretendeu ligarReader.prototype.reformat
? Se mudarmos o manipulador para uma função de seta, nos perguntaremos da mesma forma se o autor queria a dinâmicathis
, mas escolheu uma seta porque ela se encaixava em uma linha:Pode-se colocar: "É excepcional que as setas às vezes possam ser a função errada a ser usada? Talvez se raramente precisemos de
this
valores dinâmicos , ainda seria bom usar setas na maioria das vezes."Mas pergunte a si mesmo: "Valerá a pena depurar código e descobrir que o resultado de um erro foi causado por um 'caso de ponta?'" "Prefiro evitar problemas não apenas na maioria das vezes, mas 100% do tempo.
Existe uma maneira melhor: sempre use
function
(para quethis
possa sempre ser ligado dinamicamente) e sempre faça referênciathis
através de uma variável. Variáveis são lexicais e assumem muitos nomes. A atribuiçãothis
a uma variável tornará suas intenções claras:Além disso, sempre atribuir
this
a uma variável (mesmo quando houver uma únicathis
ou nenhuma outra função) garante que as intenções permaneçam claras, mesmo após a alteração do código.Além disso, a dinâmica
this
não é excepcional. O jQuery é usado em mais de 50 milhões de sites (até o momento em que este artigo foi escrito em fevereiro de 2016). Aqui estão outras APIs vinculadasthis
dinamicamente:this
.this
.this
.EventTarget
comthis
.this
.(Estatísticas via http://trends.builtwith.com/javascript/jQuery e https://www.npmjs.com .)
É provável que você
this
já exija ligações dinâmicas .Um léxico
this
é às vezes esperado, mas às vezes não; assim como uma dinâmicathis
às vezes é esperada, mas às vezes não. Felizmente, existe uma maneira melhor, que sempre produz e comunica a ligação esperada.Em relação à sintaxe concisa
As funções de seta conseguiram fornecer uma "forma sintática mais curta" para as funções. Mas essas funções mais curtas o tornarão mais bem-sucedido?
É
x => x * x
"mais fácil de ler" do quefunction (x) { return x * x; }
? Talvez seja, porque é mais provável que produza uma única linha curta de código. De acordo com Dyson A influência da velocidade de leitura e do comprimento da linha na eficácia da leitura na tela ,Justificativas semelhantes são feitas para o operador condicional (ternário) e para
if
instruções de linha única .No entanto, você está realmente escrevendo as funções matemáticas simples anunciadas na proposta ? Meus domínios não são matemáticos, portanto minhas sub-rotinas raramente são tão elegantes. Em vez disso, normalmente vejo as funções de seta quebrando um limite de coluna e quebrando em outra linha devido ao editor ou guia de estilo, que anula "legibilidade" pela definição de Dyson.
Alguém pode colocar: "Que tal usar apenas a versão curta para funções curtas, quando possível?" Mas agora uma regra estilística contradiz uma restrição de linguagem: "Tente usar a menor notação de função possível, tendo em mente que às vezes apenas a notação mais longa será vinculada
this
conforme o esperado". Essa confusão torna as flechas particularmente propensas ao mau uso.Existem vários problemas com a sintaxe da função de seta:
Ambas as funções são sintaticamente válidas. Mas
doSomethingElse(x);
não está no corpo deb
, é apenas uma afirmação de nível superior mal-recuada.Ao expandir para o formulário de bloco, não há mais um implícito
return
, que poderia ser esquecido de restaurar. Mas a expressão pode ter apenas o objetivo de produzir um efeito colateral, então quem sabe se um explícitoreturn
será necessário daqui para frente?O que pode ser pretendido como um parâmetro de descanso pode ser analisado como o operador de spread:
A atribuição pode ser confundida com argumentos padrão:
Os blocos parecem objetos:
O que isto significa?
O autor pretendia criar um no-op ou uma função que retornasse um objeto vazio? (Com isso em mente, devemos colocar o local
{
depois=>
? Devemos nos restringir apenas à sintaxe da expressão? Isso reduziria ainda mais a frequência das setas.)=>
parece<=
e>=
:Para invocar uma expressão de função de seta imediatamente, é preciso colocar
()
do lado de fora, mas a colocação()
do lado de dentro é válida e pode ser intencional.Embora, se alguém escrever
(() => doSomething()());
com a intenção de escrever uma expressão de função chamada imediatamente, simplesmente nada acontecerá.É difícil argumentar que as funções de seta são "mais compreensíveis", com todos os casos acima em mente. Um pode aprender todas as regras especiais necessárias para utilizar esta sintaxe. Isso realmente vale a pena?
A sintaxe de
function
é excepcionalmente generalizada. Usarfunction
exclusivamente significa que a própria linguagem impede que alguém escreva códigos confusos. Para escrever procedimentos que devem ser sintaticamente entendidos em todos os casos, eu escolhofunction
.Em relação a uma diretriz
Você solicita uma orientação que precisa ser "clara" e "consistente". O uso de funções de seta acabará resultando em código sintaticamente válido e logicamente inválido, com ambas as formas de função entrelaçadas, significativa e arbitrariamente. Portanto, ofereço o seguinte:
Diretriz para Notação de Função no ES6:
function
.this
a uma variável. Não use() => {}
.fonte
self
vez de um isso. Suas armadilhas de função de seta indicadas também são válidas e os mesmos padrões de outras instruções que podem ficar sem aparelho definitivamente se aplicam aqui; caso contrário, acho que, com o seu argumento, alguém poderia defender as funções das setas em todos os lugares.this
é o problema do Javascript. Em vez de estar implicitamente vinculado,this
deve ser passado como um argumento explícito.As funções de seta foram criadas para simplificar a função
scope
e resolver athis
palavra - chave, tornando-a mais simples. Eles utilizam a=>
sintaxe, que se parece com uma flecha.Nota: Não substitui as funções existentes. Se você substituir toda sintaxe de função por funções de seta, isso não funcionará em todos os casos.
Vamos dar uma olhada na sintaxe ES5 existente. Se a
this
palavra - chave estivesse dentro do método de um objeto (uma função que pertence a um objeto), a que ela se referiria?O snippet acima se refere a um
object
e imprime o nome"RajiniKanth"
. Vamos explorar o trecho abaixo e ver o que isso apontaria aqui.Agora, e se a
this
palavra - chave estivesse dentromethod’s function
?Aqui, isso se referiria ao
window object
doinner function
que ele caiuscope
. Porquethis
, sempre faz referência ao proprietário da função em que está, para este caso - já que agora está fora do escopo - a janela / objeto global.Quando está dentro do
object
método de um - ofunction
proprietário do é o objeto. Assim, a palavra-chave this está vinculada ao objeto. No entanto, quando está dentro de uma função, independente ou dentro de outro método, sempre se refere aowindow/global
objeto.Existem maneiras de resolver esse problema em
ES5
si mesmo, vamos analisar isso antes de mergulhar nas funções de seta do ES6 sobre como resolvê-lo.Normalmente, você criaria uma variável fora da função interna do método. Agora, o
‘forEach’
método obtém acessothis
e, portanto, àsobject’s
propriedades e seus valores.usando
bind
para anexar athis
palavra - chave que se refere ao método aomethod’s inner function
.Agora, com a
ES6
função de seta, podemos lidar com olexical scoping
problema de uma maneira mais simples.Arrow functions
são mais parecidas com instruções de função, exceto que sãobind
para issoparent scope
. Se o argumentoarrow function is in top scope
,this
se referir awindow/global scope
, enquanto uma função de seta dentro de uma função regular terá esse argumento igual à sua função externa.Com
arrow
funçõesthis
é vinculado ao anexoscope
no momento da criação e não pode ser alterado. O novo operador, vincular, chamar e aplicar não tem efeito nisso.No exemplo acima, perdemos o controle disso. Podemos resolver o exemplo acima usando uma referência variável
this
ou usandobind
. Com o ES6, fica mais fácil gerenciar othis
que está vinculadolexical scoping
.Quando não usar as funções de seta
Dentro de um literal de objeto.
Actor.getName
é definido com uma função de seta, mas, na chamada, ele alerta indefinido porquethis.name
éundefined
como o contexto permanecewindow
.Isso acontece porque a função seta liga o contexto lexicamente ao
window object
escopo externo. A execuçãothis.name
é equivalente awindow.name
, que é indefinido.Protótipo de objeto
A mesma regra se aplica ao definir métodos em a
prototype object
. Em vez de usar uma função de seta para definir o método sayCatName, que traz um incorretocontext window
:Invocando Construtores
this
em uma chamada de construção é o objeto recém-criado. Ao executar o novo Fn (), o contexto doconstructor Fn
é um novo objecto:this instanceof Fn === true
.this
é configurado a partir do contexto anexo, ou seja, o escopo externo que o torna não atribuído ao objeto recém-criado.Retorno de chamada com contexto dinâmico
A função Seta liga a
context
declaração estaticamente e não é possível torná-la dinâmica. Anexar ouvintes de eventos a elementos DOM é uma tarefa comum na programação do lado do cliente. Um evento aciona a função manipuladora com isso como o elemento de destino.this
é uma janela em uma função de seta definida no contexto global. Quando um evento de clique acontece, o navegador tenta chamar a função de manipulador com o contexto do botão, mas a função de seta não altera seu contexto predefinido.this.innerHTML
é equivalentewindow.innerHTML
e não faz sentido.Você deve aplicar uma expressão de função, que permita alterar isso dependendo do elemento de destino:
Quando o usuário clica no botão, isso na função do manipulador é o botão Assim,
this.innerHTML = 'Clicked button'
modifica corretamente o texto do botão para refletir o status do clique.Referências: https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
fonte
using bind to attach the this keyword that refers to the method to the method’s inner function.
tem erros de sintaxe.var Actor = { name: 'RajiniKanth', movies: ['Kabali', 'Sivaji', 'Baba'], showMovies: function() { this.movies.forEach(function(movie){ alert(this.name + ' has acted in ' + movie); }.bind(this)) } }; Actor.showMovies();
Uso: Todas as funções do ES5 devem ser substituídas pelas funções de seta do ES6, exceto nos seguintes cenários:
As funções de seta NÃO devem ser usadas:
this
/arguments
em uma funçãothis
/arguments
próprias, elas dependem de seu contexto externo.constructor
this
.this
(que deve ser o próprio objeto).Vamos entender algumas das variantes das funções das setas para entender melhor:
Variante 1 : quando queremos passar mais de um argumento para uma função e retornar algum valor dela.
Versão ES5 :
Versão ES6 :
Nota: a
function
palavra - chave NÃO é necessária.=>
É necessário.{}
são opcionais, quando não fornecemos,{}
return
é adicionado implicitamente por JavaScript e, quando fornecemos{}
, precisamos adicionar,return
se necessário.Variante 2 : Quando queremos passar apenas um argumento para uma função e retornar algum valor dela.
Versão ES5 :
Versão ES6 :
Nota: Ao passar apenas um argumento, podemos omitir parênteses
()
.Variante 3 : quando NÃO queremos passar nenhum argumento para uma função e NÃO queremos retornar nenhum valor.
Versão ES5 :
Versão ES6 :
Variante 4 : quando queremos retornar explicitamente das funções de seta.
Versão ES6 :
Variante 5 : Quando queremos retornar um objeto das funções de seta.
Versão ES6 :
Nota: Precisamos colocar o objeto entre parênteses,
()
caso contrário, o JavaScript não pode diferenciar entre um bloco e um objeto.Variante 6 : As funções de seta NÃO possuem
arguments
(um objeto semelhante a um array) próprias para as quais dependem do contexto externoarguments
.Versão ES6 :
Nota:
foo
é uma função ES5, com umaarguments
matriz como objeto e um argumento passado para ela é2
assimarguments[0]
parafoo
é 2.abc
é um ES6 arrow função uma vez que não tem o seu próprioarguments
, portanto, imprimearguments[0]
defoo
contexto externo lo de vez.Variante 7 : As funções das flechas NÃO têm
this
por si só, elas dependem do contexto externo parathis
Versão ES5 :
Nota: O retorno de chamada passado para setTimeout é uma função ES5 e possui uma função
this
que é indefinida nouse-strict
ambiente, portanto, obtemos saída:Versão ES6 :
Nota: O retorno de chamada passado para
setTimeout
é uma função de seta ES6 e NÃO possui uma função própria,this
portanto, é extraído do contexto externo que é ogreetUser
que possuithis
e,obj6
portanto, obtemos a saída:Diversos: Não podemos usar
new
com funções de seta. As funções de seta não possuemprototype
propriedade. NÃO temos ligação dethis
quando a função de seta é chamada por meio deapply
oucall
.fonte
Além das ótimas respostas até agora, gostaria de apresentar uma razão muito diferente pela qual as funções de seta são, em certo sentido, fundamentalmente melhores que as funções JavaScript "comuns". Para fins de discussão, vamos assumir temporariamente que usamos um verificador de tipos como o TypeScript ou o "Flow" do Facebook. Considere o seguinte módulo de brinquedo, que é um código ECMAScript 6 válido e anotações do tipo Flow: (incluirei o código não digitado, que resultaria realisticamente de Babel, no final desta resposta, para que possa realmente ser executado.)
Agora veja o que acontece quando usamos a classe C de um módulo diferente, assim:
Como você pode ver, o verificador de tipos falhou aqui: f2 deveria retornar um número, mas retornou uma string!
Pior, parece que nenhum verificador de tipo concebível pode lidar com funções JavaScript comuns (sem seta), porque o "this" de f2 não ocorre na lista de argumentos de f2, portanto, o tipo necessário para "this" não pode ser adicionado como uma anotação para f2.
Esse problema também afeta pessoas que não usam verificadores de tipo? Acho que sim, porque mesmo quando não temos tipos estáticos, pensamos como se eles estivessem lá. ("Os primeiros parâmetros devem ser um número, o segundo uma string" etc.). Um argumento "this" oculto que pode ou não ser usado no corpo da função dificulta nossa contabilidade mental.
Aqui está a versão executável e sem tipo, que seria produzida por Babel:
fonte
Eu ainda mantenho tudo o que escrevi na minha primeira resposta neste tópico. No entanto, minha opinião sobre o estilo do código se desenvolveu desde então, por isso tenho uma nova resposta para essa pergunta que se baseia na minha última.
Em relação ao léxico
this
Em minha última resposta, evitei deliberadamente uma crença subjacente que tenho sobre essa linguagem, pois ela não estava diretamente relacionada ao argumento que estava apresentando. No entanto, sem que isso seja explicitamente declarado, posso entender por que muitas pessoas simplesmente se recusam a recomendar que não use flechas, quando acham as flechas tão úteis.
Minha crença é a seguinte: não devemos usar
this
em primeiro lugar. Portanto, se uma pessoa evita deliberadamente o usothis
em seu código, othis
recurso " lexical " das setas tem pouco ou nenhum valor. Além disso, sob a premissa de quethis
é uma coisa ruim, o tratamento de Arrowthis
é menos uma "coisa boa"; em vez disso, é mais uma forma de controle de danos para outro recurso de linguagem ruim.Eu acho que isso não ocorre para algumas pessoas, mas mesmo para aqueles a quem ocorre, elas devem sempre trabalhar em bases de código onde
this
aparece cem vezes por arquivo e um pouco (ou muito) de controle de danos é tudo uma pessoa razoável poderia esperar. Portanto, as flechas podem ser boas, de certa forma, quando melhoram uma situação ruim.Mesmo que seja mais fácil escrever código com
this
setas do que sem elas, as regras para o uso de setas permanecem muito complexas (consulte: thread atual). Portanto, as diretrizes não são "claras" nem "consistentes", conforme solicitado. Mesmo que os programadores conheçam as ambiguidades das setas, acho que elas encolhem os ombros e as aceitam de qualquer maneira, porque o valor do lexical asthis
obscurece.Tudo isso é um prefácio para a seguinte realização: se não se usa
this
, então a ambiguidade sobrethis
essas setas normalmente causa se torna irrelevante. As setas se tornam mais neutras nesse contexto.Em relação à sintaxe concisa
Quando escrevi minha primeira resposta, eu acreditava que mesmo a adesão servil às melhores práticas era um preço a pagar, se isso significasse que eu poderia produzir um código mais perfeito. Mas acabei percebendo que a dispersão pode servir como uma forma de abstração que também pode melhorar a qualidade do código - o suficiente para justificar, às vezes, o afastamento das melhores práticas.
Em outras palavras: caramba, também quero funções de uma linha!
Em relação a uma diretriz
Com a possibilidade de
this
funções de flecha neutra, e a falta de valor valer a pena, ofereço a seguinte orientação mais branda:Diretriz para Notação de Função no ES6:
this
.fonte
Prefiro usar as funções de seta em todos os momentos em que o acesso ao local
this
não é necessário, porque a função de seta não vincula seus argumentos this, argumentos, super ou new.target .fonte
De uma maneira simples,
Outra instância:
Resp: O console imprimiria 20.
A razão é que, sempre que uma função é executada, sua própria pilha é criada, neste exemplo, a
ex
função é executada com onew
operador para que um contexto seja criado e, quandoinner
executado, o JS criaria uma nova pilha e executaria ainner
função,global context
embora haja um contexto local.Portanto, se queremos que a
inner
função tenha um contexto localex
, precisamos vincular o contexto à função interna.As setas resolvem esse problema, em vez de pegar o que
Global context
eles pegam,local context
se houver algum. Nogiven example,
que vai demorarnew ex()
comothis
.Portanto, em todos os casos em que a ligação é explícita, as setas resolvem o problema por padrão.
fonte
As funções de seta ou Lambdas foram introduzidas no ES 6. Além de sua elegância na sintaxe mínima, a diferença funcional mais notável é o escopo de
this
dentro de uma função de setaLimitações Arrow-Functions como métodos em um objeto
No caso de
objA.print()
quando oprint()
método foi definido usando regularfunction
, ele funcionou resolvendothis
corretamente aobjA
chamada de método, mas falhou quando definido como uma=>
função de seta . Isso ocorre porque,this
em uma função regular, quando invocado como método em um objeto (objA
), é o próprio objeto. No entanto, no caso de uma função de seta,this
fica lexicamente vinculado aothis
escopo de fechamento em que foi definido (global / Window no nosso caso) e permanece o mesmo durante sua chamada como método onobjA
.Vantagens de uma seta-funcionar sobre funções regulares no (s) método (s) de um objeto, MAS somente quando
this
se espera que seja corrigido e vinculado na definição de tempo.No caso em
objB.print()
que oprint()
método é definido como uma função que chamaconsole.log(
[$ {this.id} -> {this.name}] de)
forma assíncrona como retorno de chamadasetTimeout
,this
resolvida corretamenteobjB
quando uma função de seta foi usada como retorno de chamada, mas falhou quando o retorno de chamada foi definido como uma função regular. É porque a=>
função de seta passou parasetTimeout(()=>..)
fechadathis
lexicamente a partir de seu pai ou seja. invocação daobjB.print()
qual o definiu. Em outras palavras-, a seta=>
função passado para asetTimeout(()==>...
ligado paraobjB
que o seuthis
porque o na invocação deobjB.print()
this
eraobjB
si.Poderíamos facilmente usar
Function.prototype.bind()
, para fazer com que a chamada de retorno definida como uma função regular funcionasse, vinculando-a à corretathis
.No entanto, as funções de seta são úteis e menos propensas a erros no caso de retornos assíncronos, nos quais sabemos
this
o momento da definição de funções à qual ela recebe e deve estar vinculada.Limitação das funções de seta nas quais isso precisa mudar entre as invocações
A qualquer momento, precisamos de uma função que
this
possa ser alterada no momento da invocação, não podemos usar as funções de seta.Nenhuma das
const print = () => { console.log(
opções acima funcionará com a função de seta [$ {this.id} -> {this.name}],);}
poisthis
não pode ser alterada e permanecerá vinculada aothis
escopo do anexo em que foi definida (global / Window). Em todos esses exemplos, invocamos a mesma função com objetos diferentes (obj1
eobj2
) um após o outro, ambos criados após aprint()
declaração da função.Estes foram exemplos inventados, mas vamos pensar em mais alguns exemplos da vida real. Se tivéssemos que escrever nosso
reduce()
método semelhante ao que funcionaarrays
, novamente não podemos defini-lo como um lambda, porque ele precisa inferir athis
partir do contexto de invocação, ie. a matriz na qual foi invocadaPor esse motivo, as
constructor
funções nunca podem ser definidas como funções de seta, poisthis
uma função de construtor não pode ser definida no momento de sua declaração. Sempre que uma função construtora é chamada comnew
palavra - chave, é criado um novo objeto que é vinculado a essa chamada específica.Além disso, quando estruturas ou sistemas aceitam que funções de retorno de chamada sejam invocadas posteriormente com contexto dinâmico
this
, não podemos usar funções de seta, pois novamentethis
precisamos mudar a cada invocação. Essa situação geralmente ocorre com os manipuladores de eventos DOMEssa também é a razão pela qual em estruturas como Angular 2+ e Vue.js esperam que os métodos de ligação do componente do modelo sejam funções / métodos regulares,
this
pois sua chamada é gerenciada pelas estruturas das funções de ligação. (O Angular usa o Zone.js para gerenciar o contexto assíncrono para invocações de funções de ligação do modelo de exibição).Por outro lado, em React , quando queremos passar o método de um componente como manipulador de eventos, por exemplo
<input onChange={this.handleOnchange} />
, devemos definirhandleOnchanage = (event)=> {this.props.onInputChange(event.target.value);}
como uma função de seta, como para cada chamada, queremos que essa seja a mesma instância do componente que produziu o JSX para renderizado Elemento DOM.Este artigo também está disponível na minha publicação Medium . Se você gosta do artile, ou tem algum comentário e sugestão, bata palmas ou deixe comentários no Medium .
fonte