tipos - retornar valor de una funcion javascript
En JavaScript, ¿hace una diferencia si llamo a una función con paréntesis? (5)
window.onload = initAll();
Esto ejecuta initAll()
directamente y asigna el valor de retorno de la función a window.onload
. Esto usualmente no es lo que quieres. initAll()
tendría que devolver una función para que tenga sentido.
window.onload = initAll;
esto asigna la función real a window.onload
- esto es posible porque en JavaScript, como dice @Felix, las funciones son objetos de primera clase, sin ejecutarlo. initAll
será ejecutado por el evento de carga.
Noté una diferencia al llamar a una función con paréntesis vacíos, o sin ningún paréntesis. Sin embargo, no le estoy pasando ningún argumento a la función, así que me pregunté, ¿cuál sería la diferencia entre:
window.onload = initAll();
y
window.onload = initAll;
Por favor explique el principio detrás de esto.
Las funciones en javascript son ciudadanos de primera clase y, como tales, se pueden asignar a otras variables o pasar como argumentos.
Entonces, cuando lo haces
window.onload = initAll;
Está configurando la propiedad onload
del objeto window
para hacer referencia a la función initAll
.
Cuando tu lo hagas
window.onload = initAll();
Está configurando la propiedad onload
para mantener el valor de retorno de initAll, ya que se ejecutará en ese lugar en esa línea.
Lo que Pekka dice es correcto, pero quiero elaborar un poco con un ejemplo que ayude a explicar a alguien que no entiende completamente los indicadores de función o los delegados.
No window.onload
porque es un poco artificial para demostrar. Voy a usar una función de multiplicación simple para la demostración en su lugar:
function Multiply(operator, operand) {
return operator * operand;
}
Esto también podría escribirse:
Multiply = function(operator, operand) {
return operator * operand;
}
Mientras que en el primer ejemplo, la implicación puede no ser obvia, el segundo ejemplo muestra más claramente que estamos asignando una función que tiene 2 parámetros a una variable llamada Multiply
, y este concepto de funciones como asignaciones es común en todo JavaScript. Esta es una pequeña demostración del hecho de que las funciones son "ciudadanos de primera clase" , es decir, se pueden transmitir exactamente como si estuviéramos transmitiendo valores.
Entonces ahora a la diferencia de asignación:
var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);
En el momento de definir la variable ret, se ejecuta Multiply
y se asigna el valor de retorno - ret
convierte en 12.
Probemos de nuevo de una manera diferente:
var operator = 3;
var operand = 4;
var ret = Multiply;
Ahora, en el momento de definir ret
, ret
convierte en tu función Multiply
en lugar de ser el resultado obtenido de tu función Multiply
. Las llamadas a ret()
harán que se ejecute su función Multiply
, y puede llamarlo exactamente como si hubiera llamado Multiply(operator, operand)
:
var out = ret(3, 4);
es lo mismo que
var out = Multiply(3, 4);
De hecho, has dicho que vas a usar ret
como delegado para Multiply()
. Cuando llamamos ret
, realmente nos estamos refiriendo a la función Multiply
.
Regresa a tu window.onload
. Piensa en esto como:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
initAll = function() {
return 12;
}
Como puede ver, window.onload
es una función como cualquier otra función, no tiene nada de especial. Puedes asignarle un valor, asignarle una función, anularla si así lo deseas; el punto es que no hay nada más especial sobre window.onload
que sobre tu propia función. Lo único ligeramente diferente es que la ventana lo llama cuando está cargado. [Descargo de responsabilidad: nunca he anulado las funciones de la ventana, así que no estoy seguro si esto causará repercusiones negativas. Uno esperaría que verificaran si se asigna una función antes de llamarla, es decir, if (window.onload) window.onload();
]
Ahora llamando a initAll()
lo que estamos diciendo es:
window.onload = initAll();
que bien podría decir:
window.onload = 12;
Pero cuando decimos initAll
sin los paréntesis, lo que realmente estamos diciendo es: quiero reemplazar cualquiera que sea mi función window.onload, con una función nueva, es decir, quiero reemplazarla con mi función initAll
, de modo que cualquier llamada a window.onload
ejecuta mi código initAll
.
Asi que:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
es reemplazado por:
window.onload = function() {
return 12;
}
Entonces cualquier llamada a window.onload
ejecutará su función initAll
lugar de cualquier window.onload
fue originalmente. Ha reemplazado la función original con su nueva función.
De hecho, podrías escribir igualmente:
window.onload = function() {
//Write all your init code right in here instead of having a separate
//initAll function.
}
Otro ejemplo que puede demostrar mejor es este:
var d = new Date();
var currentTime = d.getTime();
Cualquiera que sea el momento en el momento en que d
se define termina asignado a currentTime
. Genial, pero eso solo es útil si queremos saber a qué hora se llamó la función que contiene ese código, es decir, en el momento de carga de la página. ¿Qué pasa si queremos la hora actual en cualquier momento que se llame a currentTime
?
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 cómo llamamos b()
en nuestras asignaciones d
exactamente como podríamos llamar currentTime()
?
Tengo 6 años de retraso, pero creo que esto podría haberse explicado mucho más simple que las respuestas anteriores.
Entonces aquí está el TLDR ; o vista de pájaro al llamar a funciones que usan y no usan ()
''s
Tomemos esta función por ejemplo:
function foo(){
return 123;
}
si registra "foo" - sin ()
console.log(foo);
---outout------
function foo(){
return 123;
}
El uso de no ()
significa recuperar la función en sí . Haría esto si desea que se transfiera como una devolución de llamada.
si registra "foo ()" - con ()
console.log(foo());
-----output-----
123
Usar ()
después de una función significa ejecutar la función y devolver su valor .
initAll
es una referencia a un valor de función y el operador de corchetes anexado al nombre de la función EJECUTA este objeto de función.
Entonces, si haces algo como
a = initAll
entonces a
se convertirá en lo mismo que initAll
- por ejemplo, puede hacer a()
- pero con
a = initAll()
la variable a
obtendrá el valor de retorno de la función initAll
ejecutada