Recentemente, comecei a manter o código JavaScript de outra pessoa. Estou corrigindo bugs, adicionando recursos e também tentando arrumar o código e torná-lo mais consistente.
O desenvolvedor anterior usou duas maneiras de declarar funções e não consigo descobrir se há uma razão por trás disso ou não.
As duas maneiras são:
var functionOne = function() {
// Some code
};
function functionTwo() {
// Some code
}
Quais são as razões para usar esses dois métodos diferentes e quais são os prós e os contras de cada um? Existe algo que possa ser feito com um método que não possa ser feito com o outro?
javascript
function
syntax
idioms
Richard Garside
fonte
fonte
var a = 1; var b = 2;
se tornavar a; var b; a = 1; b = 2
. Portanto, quando você declara functionOne, ele é declarado, mas seu valor não é definido imediatamente. Considerando que functionTwo é apenas uma declaração, ela é colocada no topo do escopo. # 2 functionTwo permite acessar a propriedade name e isso ajuda muito ao tentar depurar alguma coisa.function f(){}
vsvar f = function(){};
.Respostas:
A diferença é que
functionOne
é uma expressão de função e, portanto, é definida apenas quando essa linha é atingida, enquanto quefunctionTwo
é uma declaração de função e é definida assim que sua função ou script circundante é executado (devido à elevação ).Por exemplo, uma expressão de função:
E, uma declaração de função:
Historicamente, as declarações de funções definidas nos blocos eram tratadas de maneira inconsistente entre os navegadores. O modo estrito (introduzido no ES5) resolveu isso definindo o escopo das declarações de função para seu bloco anexo.
fonte
functionOne
é apenas uma variável que possui uma função anônima atribuída, enquantofunctionTwo
na verdade é uma função nomeada. Chame os.toString()
dois para ver a diferença. Isso é significativo em alguns casos em que você deseja obter o nome de uma função programaticamente.function expression
o segundo é umfunction declaration
. Você pode ler mais sobre o assunto aqui: javascriptweblog.wordpress.com/2010/07/06/…Primeiro, quero corrigir Greg: também
function abc(){}
tem escopo definido - o nomeabc
é definido no escopo em que essa definição é encontrada. Exemplo:Em segundo lugar, é possível combinar os dois estilos:
xyz
será definido como de costume,abc
é indefinido em todos os navegadores, exceto no Internet Explorer - não confie na definição. Mas será definido dentro de seu corpo:Se você deseja aliasar funções em todos os navegadores, use este tipo de declaração:
Nesse caso, ambos
xyz
eabc
são aliases do mesmo objeto:Um motivo convincente para usar o estilo combinado é o atributo "name" dos objetos de função ( não suportados pelo Internet Explorer ). Basicamente, quando você define uma função como
seu nome é atribuído automaticamente. Mas quando você define como
seu nome está vazio - criamos uma função anônima e a atribuímos a alguma variável.
Outro bom motivo para usar o estilo combinado é usar um nome interno curto para se referir a si mesmo, fornecendo um nome longo e não conflitante para usuários externos:
No exemplo acima, podemos fazer o mesmo com um nome externo, mas será muito difícil (e mais lento).
(Outra maneira de se referir a si mesma é usar
arguments.callee
, que ainda é relativamente longo e não é suportado no modo estrito.)No fundo, o JavaScript trata as duas instruções de maneira diferente. Esta é uma declaração de função:
abc
aqui é definido em qualquer lugar no escopo atual:Além disso, ele foi içado através de uma
return
declaração:Esta é uma expressão de função:
xyz
aqui é definido a partir do ponto de atribuição:Declaração de função vs. expressão de função é a verdadeira razão pela qual há uma diferença demonstrada por Greg.
Fato engraçado:
Pessoalmente, prefiro a declaração "expressão da função" porque dessa forma posso controlar a visibilidade. Quando eu defino a função como
Eu sei que defini a função localmente. Quando eu defino a função como
Sei que o defini globalmente, desde que não tenha definido
abc
em nenhum lugar da cadeia de escopos. Esse estilo de definição é resistente, mesmo quando usado dentroeval()
. Enquanto a definiçãodepende do contexto e pode deixá-lo adivinhando onde ele está realmente definido, especialmente no caso de
eval()
- a resposta é: depende do navegador.fonte
var abc = function(){}; console.log(abc.name);
não produz""
mais, mas"abc"
sim.Aqui está o resumo dos formulários padrão que criam funções: (Originalmente escrito para outra pergunta, mas adaptado após ser movido para a pergunta canônica).
Termos:
A lista rápida:
Declaração de Função
function
Expressão "anônima" (que, apesar do termo, às vezes cria funções com nomes)function
Expressão nomeadaInicializador da função de acessador (ES5 +)
Expressão de função de seta (ES2015 +) (que, como expressões de função anônimas, não envolve um nome explícito e ainda pode criar funções com nomes)
Declaração de método no Inicializador de Objetos (ES2015 +)
Declarações de construtor e método em
class
(ES2015 +)Declaração de Função
O primeiro formulário é uma declaração de função , com a seguinte aparência:
Uma declaração de função é uma declaração ; não é uma declaração ou expressão. Como tal, você não o segue com um
;
(embora isso seja inofensivo).Uma declaração de função é processada quando a execução entra no contexto em que aparece, antes de qualquer código passo a passo ser executado. A função que ele cria recebe um nome próprio (
x
no exemplo acima) e esse nome é colocado no escopo em que a declaração aparece.Como é processado antes de qualquer código passo a passo no mesmo contexto, você pode fazer coisas como estas:
Até ES2015, a especificação não cobrir o que um motor de JavaScript deve fazer se você colocar uma declaração de função dentro de uma estrutura de controle como
try
,if
,switch
,while
, etc., como este:E como eles são processados antes da execução do código passo a passo, é complicado saber o que fazer quando estão em uma estrutura de controle.
Embora isso não tenha sido especificado até o ES2015, era uma extensão permitida para suportar declarações de função em blocos. Infelizmente (e inevitavelmente), motores diferentes fizeram coisas diferentes.
No ES2015, a especificação diz o que fazer. De fato, ele fornece três coisas separadas para fazer:
As regras para os modos soltos são complicadas, mas, no modo estrito , as declarações de função nos blocos são fáceis: elas são locais para o bloco (elas têm escopo de bloco , o que também é novo no ES2015) e são levantadas no topo do bloco. Assim:
function
Expressão "anônima"A segunda forma comum é chamada expressão de função anônima :
Como todas as expressões, ela é avaliada quando é alcançada na execução passo a passo do código.
No ES5, a função que isso cria não tem nome (é anônimo). No ES2015, é atribuído um nome à função, se possível, deduzindo-o do contexto. No exemplo acima, o nome seria
y
. Algo semelhante é feito quando a função é o valor de um inicializador de propriedade. (Para obter detalhes sobre quando isso acontece e sobre as regras, procureSetFunctionName
na especificação - ela aparece por toda parte o lugar.)function
Expressão nomeadaA terceira forma é uma expressão de função nomeada ("NFE"):
A função que isso cria tem um nome próprio (
w
neste caso). Como todas as expressões, isso é avaliado quando é alcançado na execução passo a passo do código. O nome da função não é adicionado ao escopo em que a expressão aparece; o nome está no escopo dentro da própria função:Observe que as NFEs frequentemente são uma fonte de bugs para implementações de JavaScript. O IE8 e versões anteriores, por exemplo, lidam com as NFEs completamente incorretamente , criando duas funções diferentes em dois momentos diferentes. As versões anteriores do Safari também tinham problemas. A boa notícia é que as versões atuais dos navegadores (IE9 e posterior, Safari atual) não têm mais esses problemas. (Mas, até o momento em que este artigo foi escrito, infelizmente, o IE8 permanece em uso generalizado e, portanto, o uso de NFEs com código para a Web em geral ainda é problemático.)
Inicializador da função de acessador (ES5 +)
Às vezes, as funções podem passar despercebidas; esse é o caso das funções de acessador . Aqui está um exemplo:
Observe que, quando usei a função, não usei
()
! Isso ocorre porque é uma função de acessador para uma propriedade. Obtemos e configuramos a propriedade da maneira normal, mas nos bastidores, a função é chamada.Você também pode criar acessores funções com
Object.defineProperty
,Object.defineProperties
e o segundo argumento menos conhecido paraObject.create
.Expressão da função de seta (ES2015 +)
O ES2015 nos traz a função de seta . Aqui está um exemplo:
Vê aquela
n => n * 2
coisa escondida namap()
ligação? Essa é uma função.Algumas coisas sobre as funções de seta:
Eles não têm os seus próprios
this
. Em vez disso, eles apertada sobre othis
do contexto onde estão definidos. (Eles também fechamarguments
e, quando relevantesuper
,.) Isso significa que othis
interior deles é igual ao localthis
onde foram criados e não pode ser alterado.Como você já deve ter notado, você não usa a palavra-chave
function
; em vez disso, você usa=>
.O
n => n * 2
exemplo acima é uma forma deles. Se você tiver vários argumentos para passar a função, use parens:(Lembre-se de que
Array#map
passa a entrada como o primeiro argumento e o índice como o segundo.)Nos dois casos, o corpo da função é apenas uma expressão; o valor de retorno da função será automaticamente o resultado dessa expressão (você não usa um explícito
return
).Se você estiver fazendo mais do que apenas uma única expressão, use
{}
e um explícitoreturn
(se precisar retornar um valor), como normal:A versão sem
{ ... }
é chamada de função de seta com um corpo de expressão ou corpo conciso . (Também: uma função de seta concisa .) Aquele que{ ... }
define o corpo é uma função de seta com um corpo de função . (Também: uma função de seta detalhada .)Declaração de método no Inicializador de Objetos (ES2015 +)
O ES2015 permite uma forma mais curta de declarar uma propriedade que faz referência a uma função chamada definição de método ; Se parece com isso:
o quase equivalente no ES5 e anterior seria:
a diferença (além da verbosidade) é que um método pode usar
super
, mas uma função não. Portanto, por exemplo, se você tivesse um objeto que definisse (digamos) ovalueOf
uso da sintaxe do método, ele poderia ser usadosuper.valueOf()
para obter o valorObject.prototype.valueOf
que retornaria (antes de presumivelmente fazer outra coisa com ele), enquanto a versão do ES5 deveria fazer issoObject.prototype.valueOf.call(this)
.Isso também significa que o método tem uma referência ao objeto em que foi definido; portanto, se esse objeto é temporário (por exemplo, você o está passando
Object.assign
como um dos objetos de origem), a sintaxe do método pode significar que o objeto é retido na memória, caso contrário, poderia ter sido coletado como lixo (se o mecanismo JavaScript não detectar essa situação e tratá-la se nenhum dos métodos o usarsuper
).Declarações de construtor e método em
class
(ES2015 +)O ES2015 nos traz
class
sintaxe, incluindo construtores e métodos declarados:Há duas declarações de função acima: uma para o construtor, que obtém o nome
Person
, e outra paragetFullName
, que é uma função atribuídaPerson.prototype
.fonte
w
é simplesmente ignorado?Falando sobre o contexto global, tanto a
var
instrução quanto aFunctionDeclaration
no final criarão uma propriedade não excluível no objeto global, mas o valor de ambos pode ser substituído .A diferença sutil entre as duas maneiras é que, quando o processo de instanciação variável for executado (antes da execução real do código), todos os identificadores declarados com
var
serão inicializados comundefined
e os usados pelosFunctionDeclaration
estarão disponíveis a partir desse momento, por exemplo:A atribuição do
bar
FunctionExpression
ocorre até o tempo de execução.Uma propriedade global criada por a
FunctionDeclaration
pode ser substituída sem problemas, assim como um valor variável, por exemplo:Outra diferença óbvia entre seus dois exemplos é que a primeira função não tem um nome, mas a segunda possui, o que pode ser realmente útil na depuração (por exemplo, inspecionando uma pilha de chamadas).
Sobre o seu primeiro exemplo editado (
foo = function() { alert('hello!'); };
), é uma tarefa não declarada. Recomendamos que você sempre use avar
palavra - chave.Com uma atribuição, sem a
var
instrução, se o identificador referenciado não for encontrado na cadeia de escopo, ele se tornará uma propriedade deletável do objeto global.Além disso, atribuições não declaradas lançam um
ReferenceError
no ECMAScript 5 no Modo Estrito .Uma leitura obrigatória:
Nota : Esta resposta foi mesclada de outra pergunta , na qual a principal dúvida e o equívoco do OP eram que os identificadores declarados com a
FunctionDeclaration
não podiam ser substituídos, o que não é o caso.fonte
Os dois trechos de código publicados por você, para quase todos os fins, se comportam da mesma maneira.
No entanto, a diferença de comportamento é que, com a primeira variante (
var functionOne = function() {}
), essa função só pode ser chamada após esse ponto no código.Com a segunda variante (
function functionTwo()
), a função está disponível para o código que é executado acima do local em que a função é declarada.Isso ocorre porque, com a primeira variante, a função é atribuída à variável
foo
no tempo de execução. No segundo, a função é atribuída a esse identificadorfoo
,, no momento da análise.Mais informações técnicas
JavaScript tem três maneiras de definir funções.
eval()
, que tem seus problemas.fonte
Uma explicação melhor para a resposta de Greg
Por que nenhum erro? Sempre fomos ensinados que expressões são executadas de cima para baixo (??)
Porque:
Isso significa que um código como este:
Observe que a parte da atribuição das declarações não foi içada. Somente o nome é içado.
Mas no caso de declarações de função, todo o corpo da função também será içado :
fonte
Outros comentaristas já abordaram a diferença semântica das duas variantes acima. Eu queria observar uma diferença estilística: apenas a variação da "atribuição" pode definir uma propriedade de outro objeto.
Costumo construir módulos JavaScript com um padrão como este:
Com esse padrão, todas as suas funções públicas usarão a atribuição, enquanto as suas funções privadas usarão a declaração.
(Observe também que a atribuição deve exigir um ponto-e-vírgula após a declaração, enquanto a declaração a proíbe.)
fonte
var foo = function(){...}
sintaxe mesmo para variáveis privadas.function window.onload() {}
foi uma coisa.)Uma ilustração de quando preferir o primeiro método ao segundo é quando você precisa evitar a substituição das definições anteriores de uma função.
Com
, essa definição
myfunction
substituirá qualquer definição anterior, pois será feita no momento da análise.Enquanto
faz o trabalho correto de definir
myfunction
apenas quandocondition
é atendido.fonte
var myFunc = null;
fora de um loop ou fora de um bloco if / elseif / else. Em seguida, você pode atribuir funções diferentes à mesma variável condicionalmente. Em JS, é uma convenção melhor atribuir um valor ausente a nulo e depois a indefinido. Portanto, você deve declarar myFunction como nulo primeiro e depois atribuí-lo mais tarde, condicionalmente.Um motivo importante é adicionar uma e apenas uma variável como a "Raiz" do seu espaço para nome ...
ou
Existem muitas técnicas para namespacing. Tornou-se mais importante com a infinidade de módulos JavaScript disponíveis.
Consulte também Como declaro um espaço para nome em JavaScript?
fonte
A elevação é a ação do intérprete JavaScript de mover todas as declarações de variáveis e funções para o topo do escopo atual.
No entanto, apenas as declarações reais são içadas. deixando as tarefas onde estão.
Variável
Javascript é chamado de linguagem de tipo livre. O que significa que as variáveis Javascript podem conter o valor de qualquer Tipo de dados . O Javascript cuida automaticamente da alteração do tipo de variável com base no valor / literal fornecido durante o tempo de execução.
Função
O valor de retorno padrão da função é ' indefinido ', o valor padrão da declaração variável também 'indefinido'
Declaração de Função
Função Expressão
Função atribuída à variável Exemplo:
javascript interpretado como
Você pode verificar a declaração de função, teste de expressão em diferentes navegadores usando
jsperf Test Runner
Classes de função do construtor ES5 : objetos de função criados usando Function.prototype.bind
O JavaScript trata as funções como objetos de primeira classe; portanto, sendo um objeto, você pode atribuir propriedades a uma função.
O ES6 introduziu a função Seta : uma expressão de função seta possui uma sintaxe mais curta, é mais adequada para funções que não são de método e não pode ser usada como construtora.
fonte
Estou adicionando minha própria resposta apenas porque todo mundo cobriu a peça de elevação completamente.
Eu me pergunto sobre qual caminho é melhor há muito tempo e agora, graças a http://jsperf.com, eu sei :)
As declarações de função são mais rápidas, e é isso que realmente importa no desenvolvedor da Web, certo? ;)
fonte
Uma declaração de função e uma expressão de função atribuída a uma variável se comportam da mesma maneira quando a ligação é estabelecida.
Porém, há uma diferença de como e quando o objeto de função está realmente associado à sua variável. Essa diferença se deve ao mecanismo chamado de elevação variável no JavaScript.
Basicamente, todas as declarações de funções e variáveis são colocadas na parte superior da função em que a declaração ocorre (é por isso que dizemos que o JavaScript tem escopo de função ).
Quando uma declaração de função é içada, o corpo da função "segue"; assim, quando o corpo da função é avaliado, a variável será imediatamente ligada a um objeto de função.
Quando uma declaração de variável é hasteada, a inicialização não segue, mas é "deixada para trás". A variável é inicializada para
undefined
no início do corpo da função, e será atribuído um valor em sua posição original no código. (Na verdade, será atribuído um valor em todos os locais em que ocorre uma declaração de uma variável com o mesmo nome.)A ordem de elevação também é importante: as declarações de função têm precedência sobre as declarações de variável com o mesmo nome e a última declaração de função tem precedência sobre as declarações de função anteriores com o mesmo nome.
Alguns exemplos...
A variável
foo
é içada na parte superior da função, inicializada paraundefined
, de modo que!foo
étrue
, portanto,foo
é atribuída10
. A partefoo
externa dobar
escopo não desempenha nenhum papel e é intocada.As declarações de função têm precedência sobre as declarações de variável e a última declaração de função "adere".
Neste exemplo,
a
é inicializado com o objeto de função resultante da avaliação da segunda declaração de função e, em seguida, é atribuído4
.Aqui, a declaração da função é içada primeiro, declarando e inicializando a variável
a
. Em seguida, essa variável é atribuída10
. Em outras palavras: a atribuição não atribui à variável externaa
.fonte
O primeiro exemplo é uma declaração de função:
O segundo exemplo é uma expressão de função:
A principal diferença é como eles são içados (levantados e declarados). No primeiro exemplo, toda a declaração da função é içada. No segundo exemplo, apenas o var 'abc' é içado, seu valor (a função) será indefinido e a própria função permanece na posição em que é declarada.
Simplificando:
Para estudar mais sobre este tópico, recomendo vivamente este link
fonte
Em termos de custo de manutenção de código, as funções nomeadas são mais preferíveis:
Suspeito que mais PROS para funções nomeadas sejam seguidos. E o que está listado como uma vantagem das funções nomeadas é uma desvantagem para as funções anônimas.
Historicamente, funções anônimas apareciam pela incapacidade do JavaScript como idioma para listar membros com funções nomeadas:
fonte
Em termos de ciência da computação, falamos sobre funções anônimas e funções nomeadas. Eu acho que a diferença mais importante é que uma função anônima não está vinculada a um nome, daí o nome da função anônima. Em JavaScript, é um objeto de primeira classe declarado dinamicamente em tempo de execução.
Para mais informações sobre funções anônimas e cálculo lambda, a Wikipedia é um bom começo ( http://en.wikipedia.org/wiki/Anonymous_function ).
fonte
Uso a abordagem variável no meu código por um motivo muito específico, cuja teoria foi abordada de uma maneira abstrata acima, mas um exemplo pode ajudar algumas pessoas como eu, com conhecimentos limitados de JavaScript.
Eu tenho um código que preciso executar com 160 marcas projetadas de forma independente. A maior parte do código está em arquivos compartilhados, mas os itens específicos da marca estão em um arquivo separado, um para cada marca.
Algumas marcas exigem funções específicas e outras não. Às vezes, tenho que adicionar novas funções para fazer coisas específicas da marca. É um prazer alterar o código compartilhado, mas não quero alterar todos os 160 conjuntos de arquivos de marca.
Usando a sintaxe da variável, posso declarar a variável (um ponteiro de função essencialmente) no código compartilhado e atribuir uma função de stub trivial ou definir como nulo.
As uma ou duas marcas que precisam de uma implementação específica da função podem definir sua versão da função e atribuí-la à variável, se quiserem, e o restante não faz nada. Posso testar uma função nula antes de executá-la no código compartilhado.
Pelos comentários das pessoas acima, concluo que também é possível redefinir uma função estática, mas acho que a solução variável é boa e clara.
fonte
A resposta de Greg é boa o suficiente, mas eu ainda gostaria de acrescentar algo que aprendi agora mesmo assistindo aos vídeos de Douglas Crockford .
Expressão da função:
Instrução de função:
A declaração de função é apenas uma abreviação de
var
declaração com umfunction
valor.assim
expande para
O que se expande ainda mais para:
E ambos são elevados ao topo do código.
fonte
Há quatro comparações dignas de nota entre as duas declarações diferentes de funções, conforme listado abaixo.
O seguinte funciona porque
function add()
está com escopo definido para o bloco mais próximo:O seguinte não funciona porque a variável é chamada antes que um valor da função seja atribuído à variável
add
.O código acima é idêntico em funcionalidade ao código abaixo. Observe que atribuir explicitamente
add = undefined
é supérfluo porque simplesmente fazervar add;
é exatamente o mesmo quevar add=undefined
.O seguinte não funciona porque
var add=
substitui ofunction add()
.O nome de uma função
function thefuncname(){}
é thefuncname quando é declarado desta forma.Caso contrário, se uma função for declarada como
function(){}
, a função .name será a primeira variável usada para armazenar a função.Se não houver variáveis definidas para a função, o nome da função será a sequência vazia (
""
).Por fim, enquanto a variável à qual a função é atribuída define inicialmente o nome, as variáveis sucessivas definidas para a função não alteram o nome.
No V8 do Google e no Spidermonkey do Firefox, pode haver uma diferença de compilação no JIST de alguns microssegundos, mas, em última análise, o resultado é exatamente o mesmo. Para provar isso, vamos examinar a eficiência do JSPerf nas marcas de microbench comparando a velocidade de dois trechos de código em branco. Os testes JSPerf são encontrados aqui . E os testes do jsben.ch são encontrados aqui . Como você pode ver, há uma diferença notável quando não deve haver nenhuma. Se você é realmente um fanático por desempenho como eu, vale a pena tentar reduzir o número de variáveis e funções no escopo e principalmente eliminar o polimorfismo (como usar a mesma variável para armazenar dois tipos diferentes).
Ao usar a
var
palavra-chave para declarar uma variável, você pode reatribuir um valor diferente à variável dessa forma.No entanto, quando usamos a declaração const, a referência da variável se torna imutável. Isso significa que não podemos atribuir um novo valor à variável. Observe, no entanto, que isso não torna imutável o conteúdo da variável: se você o fizer
const arr = []
, poderá fazê-loarr[10] = "example"
. Apenas fazer algo comoarr = "new value"
ouarr = []
geraria um erro, como visto abaixo.Curiosamente, se declararmos a variável como
function funcName(){}
, então a imutabilidade da variável é a mesma que a declararvar
.Qual é o "bloco mais próximo"
O "bloco mais próximo" é a "função" mais próxima (incluindo funções assíncronas, funções de gerador e funções de gerador assíncronas). No entanto, curiosamente, um a
function functionName() {}
se comporta como umvar functionName = function() {}
quando em um bloco de não fechamento para itens fora do referido fechamento. Observar.var add=function(){}
function add(){}
if
,else
,for
,while
,try
/catch
/finally
,switch
,do
/while
,with
)var add=function()
function add()
fonte
@EugeneLazutkin dá um exemplo em que ele nomeia uma função atribuída para poder usar
shortcut()
como referência interna a si mesma. John Resig dá outro exemplo - copiar uma função recursiva atribuída a outro objeto em seu tutorial Aprendendo Javascript Avançado . Embora a atribuição de funções a propriedades não seja estritamente a questão aqui, recomendo experimentar o tutorial - execute o código clicando no botão no canto superior direito e clique duas vezes no código para editar a seu gosto.Exemplos do tutorial: chamadas recursivas em
yell()
:Os testes falham quando o objeto ninja original é removido. (página 13)
Se você nomear a função que será chamada recursivamente, os testes serão aprovados. (página 14)
fonte
Outra diferença que não é mencionada nas outras respostas é que, se você usar a função anônima
e use isso como construtor como em
então
one.constructor.name
não será definido.Function.name
não é padrão, mas é suportado pelo Firefox, Chrome, outros navegadores derivados do Webkit e IE 9+.Com
é possível recuperar o nome do construtor como uma string com
two.constructor.name
.fonte
O primeiro (função doSomething (x)) deve fazer parte de uma notação de objeto.
O segundo (
var doSomething = function(x){ alert(x);}
) é simplesmente criar uma função anônima e atribuí-la a uma variáveldoSomething
,. Então doSomething () chamará a funçãoVocê pode querer saber o que é uma declaração e expressão de função .
Uma declaração de função define uma variável de função nomeada sem exigir a atribuição de variáveis. As declarações de função ocorrem como construções independentes e não podem ser aninhadas em blocos não funcionais.
Na condição acima, o nome da função é visível dentro de seu escopo e do escopo de seu pai (caso contrário, seria inacessível).
E em uma expressão de função
Uma expressão de função define uma função como parte de uma sintaxe de expressão maior (geralmente uma atribuição de variável). As funções definidas por meio de expressões de funções podem ser nomeadas ou anônimas. As expressões de função não devem começar com "function".
fonte
Estou listando as diferenças abaixo:
Uma declaração de função pode ser colocada em qualquer lugar do código. Mesmo que seja invocada antes que a definição apareça no código, ela é executada quando a declaração da função é confirmada na memória ou de uma maneira que é içada, antes de qualquer outro código na página iniciar a execução.
Dê uma olhada na função abaixo:
Isso ocorre porque, durante a execução, parece:
Uma expressão de função, se não for definida antes de chamá-la, resultará em um erro. Além disso, aqui a própria definição de função não é movida para o topo ou confirmada na memória, como nas declarações de função. Mas a variável à qual atribuímos a função é içada e indefinida é atribuída a ela.
Mesma função usando expressões de função:
Isso ocorre porque durante a execução, parece com:
Não é seguro escrever declarações de função em blocos não funcionais como se não estivessem acessíveis.
Expressão de função nomeada como a abaixo, pode não funcionar nos navegadores Internet Explorer anteriores à versão 9.
fonte
Se você usasse essas funções para criar objetos, obteria:
fonte
console.log(objectOne.__proto__);
imprime "functionOne {}" no meu console. Alguma idéia de por que isso pode ser o caso?À luz do argumento "funções nomeadas aparecem nos rastreamentos de pilha", os modernos mecanismos JavaScript são realmente capazes de representar funções anônimas.
No momento da redação deste documento, V8, SpiderMonkey, Chakra e Nitro sempre se referem às funções nomeadas por seus nomes. Eles quase sempre se referem a uma função anônima pelo seu identificador, se houver.
SpiderMonkey pode descobrir o nome de uma função anônima retornada de outra função. O resto não pode.
Se você realmente queria que seu iterador e retornos de sucesso aparecessem no rastreamento, também poderia nomear esses ...
Mas, na maioria das vezes, não vale a pena enfatizar.
Arnês ( Fiddle )
V8
Macaco aranha
Chakra
Nitro
fonte
No JavaScript, existem duas maneiras de criar funções:
Declaração de função:
Isso é muito básico, autoexplicativo, usado em muitos idiomas e padrão na família C de idiomas. Declaramos que uma função a definiu e a executou chamando-a.
O que você deveria saber é que funções são realmente objetos em JavaScript; internamente, criamos um objeto para a função acima e atribuímos a ele um nome chamado fn ou a referência ao objeto é armazenada em fn. Funções são objetos em JavaScript; uma instância da função é na verdade uma instância do objeto.
Expressão da função:
O JavaScript possui funções de primeira classe, ou seja, crie uma função e atribua-a a uma variável, assim como você cria uma sequência ou número e atribui-a a uma variável. Aqui, a variável fn é atribuída a uma função. A razão para esse conceito é que funções são objetos em JavaScript; fn está apontando para a instância do objeto da função acima. Inicializamos uma função e a atribuímos a uma variável. Não está executando a função e atribuindo o resultado.
Referência: sintaxe da declaração da função JavaScript: var fn = function () {} vs function fn () {}
fonte
var fn = function fn() {...}
?Ambas são formas diferentes de definir uma função. A diferença é como o navegador as interpreta e as carrega em um contexto de execução.
O primeiro caso é de expressões de função que são carregadas apenas quando o intérprete atinge essa linha de código. Portanto, se você fizer o seguinte, você receberá um erro dizendo que a functionOne não é uma função .
O motivo é que, na primeira linha, nenhum valor é atribuído a functionOne e, portanto, é indefinido. Estamos tentando chamá-lo como uma função e, portanto, estamos recebendo um erro.
Na segunda linha, estamos atribuindo a referência de uma função anônima a functionOne.
O segundo caso é de declarações de função que são carregadas antes que qualquer código seja executado. Portanto, se você gosta do seguinte, não receberá nenhum erro, pois a declaração é carregada antes da execução do código.
fonte
Sobre o desempenho:
Novas versões
V8
introduziram várias otimizações ocultas e o mesmo aconteceuSpiderMonkey
.Não há quase nenhuma diferença agora entre expressão e declaração.
A expressão da função parece ser mais rápida agora.
Chrome 62.0.3202
FireFox 55
Chrome Canary 63.0.3225
Firefox Chrome Canary Chrome
fonte
Eles são bem parecidos com algumas pequenas diferenças, a primeira é uma variável atribuída a uma função anônima (Declaração de Função) e a segunda é a maneira normal de criar uma função em JavaScript (Declaração de Função Anônima), ambas com uso, contras e prós. :
1. Expressão de Função
Atribua uma variável a uma função, significa que nenhum Hoisting, como sabemos que funções em JavaScript podem Hoist, significa que elas podem ser chamadas antes de serem declaradas, enquanto as variáveis precisam ser declaradas antes de ter acesso a elas, portanto, neste caso, não podemos acessar a função antes de onde é declarada, também pode ser uma maneira de você escrever suas funções; para as funções que retornam outra função, esse tipo de declaração pode fazer sentido; também no ECMA6 e acima, você pode atribuir isso a uma função de seta que pode ser usado para chamar funções anônimas, também esta maneira de declarar é a melhor maneira de criar funções do Construtor em JavaScript.
2. Declaração de Função
Essa é a maneira normal de chamar uma função em JavaScript; essa função pode ser chamada antes mesmo de declará-la, pois em JavaScript todas as funções são Hoisted, mas se você tiver 'use strict', isso não será Hoist conforme o esperado, é uma boa maneira. chamar todas as funções normais que não são grandes em linhas e nem são uma função construtora.
Além disso, se você precisar de mais informações sobre como o içamento funciona em JavaScript, visite o link abaixo:
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
fonte
...also this way of declaring is a better way to create Constructor functions in JavaScript
, você pode elaborar, estou curioso!Esta é apenas duas maneiras possíveis de declarar funções e, na segunda maneira, você pode usar a função antes da declaração.
fonte
new Function()
pode ser usado para passar o corpo da função em uma string. E, portanto, isso pode ser usado para criar funções dinâmicas. Também passando o script sem executar o script.fonte