2010-09-04 11 views
19

Ahora, yo suelo llamar una función (que no requiere de argumentos) con () así:¿Cuál es el significado de "()" en una llamada a función?

myFunction(); //there's empty parens 

Excepto en jQuery llamadas donde pueda salirse con:

$('#foo').bind('click', myFunction); //no parens 

fina. Sin embargo, recientemente vi este comentario here en SO:

"Considere el uso de setTimeout(monitor, 100); en lugar de setTimeout('monitor()', 100); Eval es malo :)."

Huy! ¿Estamos realmente eval()? ¿Estamos aquí? Supongo que realmente no entiendo la importancia y las implicaciones de 'llamar' a una función. ¿Cuáles son las reglas reales sobre llamar y referirse a funciones?

Respuesta

44

En las funciones de JavaScript se encuentran objetos de primera clase. Eso significa que puede pasar funciones como parámetros a una función, o tratarlas como variables en general.

Digamos que estamos hablando de una función hello,

function hello() { 
    alert('yo'); 
} 

Cuando simplemente escribimos

hello 

nos estamos refiriendo a la función que no ejecute su contenido. Pero cuando añadimos los parens () después de que el nombre de la función,

hello() 

continuación, en realidad estamos llamando a la función que alertará "yo" en la pantalla.

El método bind en jQuery acepta el tipo de evento (cadena) y una función como sus argumentos. En su ejemplo, está pasando el tipo - "clic" y la función real como argumento.

¿Has visto Inception? Considere este ejemplo artificial que podría aclarar las cosas. Como las funciones son objetos de primera clase en JavaScript, podemos pasar y devolver una función desde dentro de una función. Entonces creamos una función que devuelve una función cuando se invoca, y la función devuelta también devuelve otra función cuando se invoca.

function reality() { 
    return function() { 
     return function() { 
      alert('in a Limbo'); 
     } 
    }; 
} 

Aquí reality es una función, reality() es una función, y reality()() es una función también. Sin embargo, reality()()() no es una función, sino simplemente undefined ya que no estamos devolviendo una función (no estamos devolviendo nada) desde la función más interna.

Por lo tanto, para el ejemplo de función reality, podría haber pasado cualquiera de los siguientes al enlace de jQuery.

$('#foo').bind('click', reality); 
$('#foo').bind('click', reality()); 
$('#foo').bind('click', reality()()); 
+8

Extrañamente, eso no solucionó nada. –

+2

Yay, ahora tengo el récord de usar "función" el mayor número de veces de todas las respuestas SO - 27. – Anurag

+3

+1 para referencia de inicio (y para una buena explicación, por supuesto) – delnan

3

usted no está haciendo lo mismo en su ejemplo jQuery como en el segundo ejemplo setTimeout - en su código está de paso la función y vinculante el evento click.

En la primera setTimout ejemplo, la función monitor se pasa en y puede ser invocado directamente, en la segunda, la picadura monitor() se pasa en y necesita ser eval ed.

Al pasar una función, utiliza el nombre de la función. Al invocarlo, necesita usar el ().

Eval invocará lo que se transfiere, por lo que se requiere () para una invocación de función exitosa.

+0

¿Entonces el comentario es incorrecto? Realmente debería pasar 'setTimeout (monitor(), 100); // nota los parens'? –

+0

@Isaac Lubow: No, el código es correcto, es solo que estás haciendo algo diferente en cada parte del código. Los dos ejemplos no son lo mismo. –

+0

Si desea que el 'monitor' se ejecute después de 100 ms, usted haría' setTimeout (monitor(), 100); // nota los parens? '¿entonces? –

7

El ejemplo de jQuery bind es similar al setTimeout(monitor, 100);, está pasando una referencia de un objeto de función como argumento.

pasar una cadena a los métodos setTimeout/setInterval deben ser evitados por las mismas razones que usted debe evitar eval y el constructor Function cuando no es necesario.

El código se pasa como una cadena serán evaluados y se ejecutan en el contexto de ejecución global, lo que le puede dar "problemas de alcance", consideremos el siguiente ejemplo:

// a global function 
var f = function() { 
    alert('global'); 
}; 

(function() { 
    // a local function 
    var f = function() { 
    alert('local'); 
    }; 

    setTimeout('f()', 100); // will alert "global" 
    setTimeout(f, 100);  // will alert "local" 
})(); 

La primera setTimeout llamada en el ejemplo anterior , ejecutará la función global f, porque el código evaluado no tiene acceso al alcance léxico local de la función anónima.

Si pasa la referencia de un objeto de función al método setTimeout -como en la segunda llamada setTimeout- se ejecutará exactamente la misma función que usted refiere en el alcance actual.

2

En primer lugar, "()" no es parte del nombre de la función. Es la sintaxis utilizada para realizar llamadas a funciones.

En primer lugar, se enlaza una función a un nombre de identificación, ya sea usando una declaración de función:

function x() { 
    return "blah"; 
} 

... o mediante el uso de una expresión de función:

var x = function() { 
    return "blah"; 
}; 

Ahora, siempre que lo desee para ejecutar esta función, use los parens:

x(); 

La función setTimeout acepta ambos y el identificador de una función, o una cadena como primer argumento ...

setTimeout(x, 1000); 
setTimeout("x()", 1000); 

Si proporciona un identificador, entonces se llamará como una función. Si proporciona una cadena, se evaluará (ejecutará).

Se prefiere el primer método (que proporciona un identificador) ...

+0

'Si proporciona un identificador, se llamará como una función. Si proporciona una cadena, entonces se evaluará (ejecutará) .' ¿Puede explicar la diferencia? –

+0

@Isaac Si proporciona una cadena, esta secuencia se ejecutará como código JavaScript. Por ejemplo: 'setTimeout ('x = 3;', 100)'. Como puede ver, no se llama ninguna función aquí. La cadena ''x = 3; '' se evalúa como una expresión de asignación. Por otro lado, si proporciona un nombre de identificador, este nombre debe apuntar a un objeto de función (que luego se llamará). –

+0

Gotcha. Gracias. –

Cuestiones relacionadas