Em JavaScript, faz diferença se eu chamo uma function com parênteses?

Percebi uma diferença ao chamar uma function com parênteses vazios ou sem parênteses. No entanto, eu não estou passando nenhum argumento para a function, então eu me perguntei qual seria a diferença entre:

window.onload = initAll(); 

e

 window.onload = initAll; 

Por favor, explique o princípio por trás disso.

 window.onload = initAll(); 

Isso executa initAll() imediatamente e atribui o valor de retorno da function a window.onload . Isso geralmente não é o que você quer. initAll() teria que retornar uma function para fazer sentido.

 window.onload = initAll; 

isto atribui a function real a window.onload – isto é possível porque em JavaScript, como @Felix diz, funções são objects de primeira class – sem executá-lo. initAll será executado pelo evento de carregamento.

O que Pekka diz está correto, mas quero elaborar um pouco com um exemplo que ajudará a explicar a alguém que não entende completamente os pointers ou delegates da function.

Eu não vou usar window.onload porque isso é um pouco artificial para demonstrar. Vou usar uma function simples de multiplicação para demonstração:

 function Multiply(operator, operand) { return operator * operand; } 

Isto poderia igualmente ser escrito:

 Multiply = function(operator, operand) { return operator * operand; } 

Enquanto no primeiro exemplo, a implicação pode não ser óbvia, o segundo exemplo mostra mais claramente que estamos atribuindo uma function que tem 2 parâmetros para uma variável chamada Multiply , e esse conceito de funções como atribuições é comum em todo o JavaScript. Esta é uma pequena demonstração do fato de que funções são “cidadãos de primeira class” , isto é, eles podem ser passados ​​exatamente como se estivéssemos passando valores.

Então, agora para a diferença de atribuição:

 var operator = 3; var operand = 4; var ret = Multiply(operator, operand); 

No momento de definir a variável ret, o Multiply é executado e o valor de retorno é atribuído – ret torna-se igual a 12.

Vamos tentar de novo de uma maneira diferente:

 var operator = 3; var operand = 4; var ret = Multiply; 

Agora, no ponto de definir ret , ret torna-se sua function Multiply , em vez de ser o resultado obtido da sua function Multiply . Chamadas para ret() farão com que sua function Multiply seja executada, e você pode chamar exatamente como se tivesse chamado Multiply(operator, operand) :

 var out = ret(3, 4); 

é o mesmo que

 var out = Multiply(3, 4); 

Você efetivamente disse que você vai usar ret como um delegado para Multiply() . Ao chamar ret , estamos realmente nos referindo à function Multiply .

De volta ao seu window.onload . Pense nisso como:

 window.onload = function() { //Doing what all good window.onload functions should do... } initAll = function() { return 12; } 

Então, como você pode ver, window.onload é uma function como qualquer outra function, não há nada de especial nisso. Você pode atribuir-lhe um valor, atribuir-lhe uma function, anular se quiser – o ponto é que não há nada mais especial sobre window.onload do que sobre sua própria function. A única coisa diferente é que ela é chamada pela janela quando é carregada. [Aviso: Eu nunca anulei as funções da janela, então não tenho certeza se isso causará repercussões negativas. Espera-se que eles verifiquem se uma function é atribuída antes de chamá-la, ie if (window.onload) window.onload(); ].

Agora chamando initAll() o que estamos dizendo é:

 window.onload = initAll(); 

o que pode muito bem dizer:

 window.onload = 12; 

Mas quando dizemos initAll sem os parênteses, o que estamos realmente dizendo é: Eu quero replace qualquer que seja minha function window.onload, com uma nova function – ou seja, eu quero substituí-la pela minha function initAll , para que qualquer chamada para window.onload executa o meu código initAll .

Assim:

 window.onload = function() { //Doing what all good window.onload functions should do... } 

é substituído por:

 window.onload = function() { return 12; } 

Portanto, qualquer chamada para window.onload executará sua function initAll vez de qualquer initAll . Você substituiu a function original pela sua nova function.

De fato, você poderia igualmente escrever:

 window.onload = function() { //Write all your init code right in here instead of having a separate //initAll function. } 

Outro exemplo que pode demonstrar melhor é isso:

 var d = new Date(); var currentTime = d.getTime(); 

Seja qual for o tempo no momento em que d é definido, ele será atribuído a currentTime . Ótimo, mas isso só é útil se quisermos descobrir a que horas a function que contém esse código foi chamada – ou seja, no tempo de carregamento da página. E se quisermos a hora atual sempre que o currentTime for chamado?

 var currentTime = function() { var d = new Date(); return d.getTime(); } var a = currentTime(); //The current time at the point a is defined... var b = currentTime; //b is a functional reference to currentTime... var c = b(); //The current time when variable c is defined var d = c; //The current time when variable c was defined 

Observe como chamamos b() em nossas atribuições c exatamente como poderíamos chamar currentTime() ?

Funções em javascript são cidadãos de primeira class e, como tal, podem ser atribuídos a outras variables ​​ou passados ​​como argumentos.

Então, quando você faz

 window.onload = initAll; 

Você está definindo a propriedade onload do object window para referenciar a initAll function initAll .

Quando você faz

 window.onload = initAll(); 

Você está definindo a propriedade onload para manter o valor de retorno de initAll, já que ele será executado nessa linha.

initAll é uma referência a um valor de function e o operador de colchetes anexado ao nome da function RUNS este object de function.

Então, se você fizer algo como

 a = initAll 

então a vai se tornar o mesmo que initAll – por exemplo, você pode fazer a() – mas com

 a = initAll() 

a variável a irá obter o valor de retorno da function initAll executada

Estou com 6 anos de atraso, mas acho que isso poderia ter sido explicado muito mais simples do que as respostas acima.

Então aqui está o TLDR ; ou vista aérea ao chamar funções usando e não usando () ‘s

Vamos pegar essa function por exemplo:

 function foo(){ return 123; } 

se você logar “foo” – sem ()

 console.log(foo); ---outout------ function foo(){ return 123; } 

Usar no () significa buscar a function em si . Você faria isso se quiser que ele seja passado como um retorno de chamada.


se você logar “foo ()” – com ()

 console.log(foo()); -----output----- 123 

Usar () depois de uma function significa executar a function e retornar seu valor .