Diferencia entre setTimeout con y sin comillas y paréntesis

241

Estoy aprendiendo JavaScript y recientemente he aprendido sobre eventos de sincronización de JavaScript. Cuando me enteré setTimeouten W3Schools , noté una figura extraña con la que no me había encontrado antes. Están usando comillas dobles y luego llaman a la función.

Ejemplo:

setTimeout("alertMsg()", 3000);

Sé que las comillas dobles y simples en JavaScript significan una cadena.

También vi que puedo hacer lo mismo así:

setTimeout(alertMsg, 3000);

Con los paréntesis se refiere, sin los paréntesis se copia. Cuando estoy usando las comillas y los paréntesis, se está volviendo loco.

Me alegraría si alguien me puede explicar la diferencia entre estas tres formas de uso setTimeout:

Con los paréntesis:

setTimeout("alertMsg()", 3000);

Sin las comillas y los paréntesis:

setTimeout(alertMsg, 3000);

Y el tercero solo usa comillas:

setTimeout("alertMsg", 3000);

NB: Una mejor fuente de setTimeoutreferencia sería MDN .

usuario1316123
fuente
55
@Jefffrey, ese sitio web de w3fools no dice que el contenido allí es incorrecto, solo que podría estar desactualizado y faltar algunas de las cosas más nuevas. Debería estar bien para usar como referencia para (o para aprender) las cosas principales. Puedo entender que las personas se sientan frustradas por la forma en que intentan parecer parte de w3, pero eso no resta valor al contenido. Está bien diseñado y es fácil de leer con ejemplos claros, perfecto para los novatos.
Mateo
14
@Matthew "Sin embargo, creemos que W3Schools está perjudicando a la comunidad con información inexacta". - dentro de las primeras tres líneas.
Zapato
1
@Jefffrey, sí, vi eso, pero más abajo, donde explican lo que no les gusta, en la sección "W3Schools es un problema", ninguna de las tres razones que dan tienen algo que ver con información inexacta. No tienen un solo ejemplo de nada que esté realmente "mal". Sus quejas son que no dicen explícitamente que no están afiliados a w3, cobran por certificaciones no reconocidas y no se actualizan rápidamente con nuevo contenido (por ejemplo, html 5).
Mateo
10
@Matthew, información desactualizada, en lenguajes delicados como Javascript, SQL o PHP, es lo que guía a las masas de programadores aspirantes a adherirse a tecnologías antiguas y potencialmente peligrosas (como la mysql_extensión de PHP) de las cuales la secuencia de preguntas SO es solo un ejemplo. IIRC también hubo algunos errores muy sutiles en la sección SQL, pero ha pasado casi un año desde la última vez que visité el sitio web y muchos de ellos también podrían repararse. E incluso si todo lo anterior fuera perfecto, no promocionaría un sitio web que intente engañar a las personas con el fraude de su certificado.
Zapato
44
Dejando a un lado las certificaciones sombrías, es un recurso de referencia decente y es contraproducente para todo el punto de SO denunciarlas.
worc

Respuestas:

383

Usando setIntervalosetTimeout

Debe pasar una referencia a una función como primer argumento para setTimeouto setInterval. Esta referencia puede ser en forma de:

  • Una función anónima

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Un nombre de una función existente

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Una variable que apunta a una función existente.

    var foo = function(){...};
    
    setTimeout(foo, 2000);

    Tenga en cuenta que establezco "variable en una función" por separado del "nombre de la función". No es evidente que las variables y los nombres de las funciones ocupen el mismo espacio de nombres y puedan golpearse entre sí.

Pasando argumentos

Para llamar a una función y pasar parámetros, puede llamar a la función dentro de la devolución de llamada asignada al temporizador:

setTimeout(function(){
  foo(arg1, arg2, ...argN);
}, 1000);

Hay otro método para pasar argumentos al controlador, sin embargo, no es compatible con varios navegadores .

setTimeout(foo, 2000, arg1, arg2, ...argN);

Contexto de devolución de llamada

Por defecto, el contexto de la devolución de llamada (el valor de thisdentro de la función llamada por el temporizador) cuando se ejecuta es el objeto global window. Si desea cambiarlo, úselo bind.

setTimeout(function(){
  this === YOUR_CONTEXT; // true
}.bind(YOUR_CONTEXT), 2000);

Seguridad

Aunque es posible, no debe pasar una cadena a setTimeouto setInterval. Pasar una cadena crea setTimeout()o setInterval()usa una funcionalidad similar a la eval()que ejecuta cadenas como secuencias de comandos , lo que hace posible la ejecución de secuencias de comandos arbitrarias y potencialmente dañinas.

Joseph
fuente
he aprendido que cuando usa solo el nombre de la función, la función se copia, entonces, ¿por qué dice en su primer ejemplo que setTumeout foo (function) pass reference se copia la función que he inclinado? y me puedes contar más por favor sobre la evaluación por favor.
user1316123
42
Las funciones de @ user1316123 nunca se copian. lo mismo con objetos y matrices. se pasan por referencia . deberías dejar de leer w3schools. están haciendo más daño que bien
Joseph
44
Las funciones de @JosephtheDreamer son objetos. "Un nombre de función" y "Una variable que se refiere a una función" es lo mismo . Además, puede pasar parámetros a setTimeout directamente (no es necesario envolverlo en un lambda (aunque, como dijiste, navegadores más nuevos). Además, el problema no es permitir que los usuarios ejecuten scripts (siempre pueden hacer esto de todos modos), es mediante la aceptación de las aportaciones de otros usuarios y en funcionamiento que como secuencia de comandos el propio usuario siempre puede abrir la consola y ejecutar JavaScript arbitrario..
Benjamin Gruenbaum
@BenjaminGruenbaum Estaba a punto de hacer un comentario casi idéntico a su segunda oración. Risa :)
ErikE
2
No me di cuenta de que necesitabas usar una función para que setTimeout funcionara correctamente. Gracias por aclarar eso.
Matt Dell
3

Creo que la función setTimeout que escribes no se está ejecutando. si usa jquery, puede hacer que se ejecute correctamente haciendo esto:

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });
Acil Az
fuente
I thinkink Al igual que usted, pero el enlace w3schools.com/js/js_timing.asp dice algo más
user1316123
si entiendo correctamente cuando uso Brackets, puedo referirme solo a la función que contiene el método setTimeout porque la función ¿Disponible en los corchetes solo en su ámbito local?
user1316123
2

Totalmente de acuerdo con Joseph.

Aquí hay un violín para probar esto: http://jsfiddle.net/nicocube/63s2s/

En el contexto del violín, el argumento de cadena no funciona, en mi opinión porque la función no está definida en el ámbito global.

Nicocube
fuente
w3schools.com/js/js_timing.asp si se puede entrar en el enlace y ver por favor lástima pues José dice que su peligroso, pero si se introduce el enlace de su trabajo
user1316123
chicos, miren esto: quirksmode.org/js/this.html este enlace dice que se puede copiar un func
user1316123
Sí puede, porque las funciones son objeto en JS. El problema con eval es que evaluará en contexto global y no podrá obtener el contexto local que ocurre con un violín.
Nicocube
¿Puedes explicar en algunas palabras sobre eval por favor?
user1316123
Algunas buenas explicaciones: javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval
Nicocube
1

Lo que sucede en realidad en caso de que pase una cadena como primer parámetro de función

setTimeout ( 'string', number)

Este valor del primer parámetro se evaluó cuando es hora de ejecutarse (después numberde transcurridos milisegundos). Básicamente es igual a

setTimeout ( eval('string'), number)

Esto es

una sintaxis alternativa que le permite incluir una cadena en lugar de una función, que se compila y ejecuta cuando expira el temporizador. Esta sintaxis no se recomienda por las mismas razones que hacen que el uso de eval () sea un riesgo para la seguridad.

Por lo tanto, las muestras a las que se refiere no son buenas muestras y se pueden dar en un contexto diferente o simplemente un error tipográfico.

Si invoca de esta manera setTimeout(something, number), el primer parámetro no es una cadena, sino un puntero a algo llamado something. Y nuevamente si somethinges una cadena, entonces se evaluará. Pero si es función, entonces la función se ejecutará. muestra jsbin

Vitaliy Markitanov
fuente
0
    ##If i want to wait for some response from server or any action we use setTimeOut.

    functionOne =function(){
    console.info("First");

    setTimeout(()=>{
    console.info("After timeOut 1");
    },5000);
    console.info("only setTimeOut() inside code waiting..");
    }

    functionTwo =function(){
    console.info("second");
    }
    functionOne();
    functionTwo();

## So here console.info("After timeOut 1"); will be executed after time elapsed.
Output:
******************************************************************************* 
First
only setTimeOut() inside code waiting..
second
undefined
After timeOut 1  // executed after time elapsed.
Avinash Khadsan
fuente
-1

Con los paréntesis:

setTimeout("alertMsg()", 3000); // It work, here it treat as a function

Sin las comillas y los paréntesis:

setTimeout(alertMsg, 3000); // It also work, here it treat as a function

Y el tercero solo usa comillas:

setTimeout("alertMsg", 3000); // It not work, here it treat as a string

function alertMsg1() {
        alert("message 1");
    }
    function alertMsg2() {
        alert("message 2");
    }
    function alertMsg3() {
        alert("message 3");
    }
    function alertMsg4() {
        alert("message 4");
    }

    // this work after 2 second
    setTimeout(alertMsg1, 2000);

    // This work immediately
    setTimeout(alertMsg2(), 4000);

    // this fail
    setTimeout('alertMsg3', 6000);

    // this work after 8second
    setTimeout('alertMsg4()', 8000);

En el ejemplo anterior, primero llame a la función alertMsg2 () inmediatamente (le damos el tiempo de espera 4S pero no molesta) después de ese alertMsg1 () (Una espera de 2 segundos) y luego alertMsg4 () (Una espera de 8 segundos) pero alertMsg3 () no funciona porque lo colocamos entre comillas sin partes, por lo que se trata como una cadena.

Srikrushna
fuente
Demuestra los escenarios sobre los que pregunta el interrogador, pero en realidad no responde la pregunta. No veo lo que esto agrega sobre las respuestas existentes de 6 años .
Stephen P