2012-07-27 26 views
5

Sé que eval y setTimeout pueden aceptar una cadena como el (1er) parámetro, y sé que será mejor que no use esto. Tengo curiosidad por qué hay una diferencia:Diferencia entre eval y setTimeout ejecutar código de cadena

!function() { 
    var foo = 123; 
    eval("alert(foo)"); 
}(); 

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

la primera quiere trabajar, y el segundo dará un error: foo is not defined

¿Cómo están ejecutados detrás de la escena?

+1

¿se sale de alcance antes de llamar a la devolución de llamada setTimeout? –

+1

¿Por qué meterse con cosas malvadas? ^^ No use ninguno de estos :) – Andreas

+0

Un interesante punto de vista relacionado [aquí] (https://stackoverflow.com/q/3492015/465053). – RBT

Respuesta

4

Véase el reference of setTimeout on MDN.

String literals are evaluated in the global context, so local symbols in the context where setTimeout() was called will not be available when the string is evaluated as code.

Por el contrario, la cadena literal pasado a eval() se ejecuta en el contexto de la llamada a eval.

+0

y el código pasado a 'eval' se ejecutará en el contexto donde' eval' se está ejecutando? – wong2

+0

Exactamente, el literal de cadena se evalúa "in situ" y tiene acceso a las variables definidas en ese contexto. – Wolfram

+0

@ wong2 en realidad depende de cómo se llame 'eval'. En los navegadores modernos, la siguiente evaluación está en alcance global: http://jsfiddle.net/4p9QY/ porque es una evaluación indirecta. Aquí hay más ejemplos de llamadas indirectas de evaluación http://perfectionkills.com/global-eval-what-are-the-options/#indirect_eval_call_examples – Esailija

2

setTimeout's eval se ejecuta adicionalmente en alcance global, por lo que no tiene conocimiento de foo.

Aquí es reference que lo respalde:

String literals are evaluated in the global context, so local symbols in the context where setTimeout() was called will not be available when the string is evaluated as code.

0
!function() { 
    var foo = 123; 
    eval("alert(foo)"); 
}(); 

Al ejecutar este código, javascript simulará que la línea 3 dice "alerta (foo)". Foo se define en el alcance de la función.

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

Al ejecutar este código, javascript ingresará una nueva función; es decir, function() {alert(foo)}. En el alcance de esa función 'nueva', foo no está definido.

1

setTimeout toma más parámetros que la referencia de función y el tiempo de espera. Todo lo que ingrese pasado el tiempo de espera pasará a su función como parámetro.

setTimeout(myFunction(param1, param2), 0, param1, param2); 
0

Como complemento a la respuesta correcta, aquí es una llamada a eval que le daría el mismo comportamiento, y el error en estos casos:

!function() { 
    var foo = 123; 
    window.eval("alert(foo)"); // <- note the window.eval, this is important and changes the behavior of the `eval` function 
}(); 

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

Este blog va en profundidad sobre la diferentes tipos de eval: http://perfectionkills.com/global-eval-what-are-the-options/

Cuestiones relacionadas