Differenza tra setTimeout con e senza virgolette e parentesi


241

Sto imparando JavaScript e ho imparato di recente sugli eventi di temporizzazione JavaScript. Quando ho imparato a conoscere setTimeouta W3Schools , ho notato una strana figura che non ho incontrato prima. Stanno usando le virgolette doppie e quindi chiamano la funzione.

Esempio:

setTimeout("alertMsg()", 3000);

So che le virgolette doppie e singole in JavaScript significano una stringa.

Inoltre ho visto che posso fare lo stesso in questo modo:

setTimeout(alertMsg, 3000);

Con le parentesi si riferisce, senza le parentesi viene copiato. Quando sto usando le virgolette e le parentesi diventa pazzo.

Sarò felice se qualcuno mi può spiegare la differenza tra questi tre modi di usare setTimeout:

Con le parentesi:

setTimeout("alertMsg()", 3000);

Senza virgolette e parentesi:

setTimeout(alertMsg, 3000);

E il terzo utilizza solo le virgolette:

setTimeout("alertMsg", 3000);

NB: una migliore fonte di setTimeoutriferimento sarebbe MDN .


5
@Jefffrey quel sito web di w3fools non dice che il contenuto è sbagliato, solo che potrebbe essere obsoleto e perdere alcune delle cose più recenti. Va bene usare come riferimento per (o per imparare) le cose fondamentali. Riesco a capire che le persone sono frustrate dal modo in cui cercano di sembrare parte di w3, ma ciò non toglie nulla al contenuto. È ben strutturato e facile da leggere con esempi chiari, perfetto per i noob.
Matteo

14
@Matthew "Riteniamo, tuttavia, che W3Schools stia danneggiando la comunità con informazioni imprecise." - entro le prime tre righe.
Scarpa

1
@Jefffrey sì, l'ho visto, ma più in basso, dove spiegano cosa non gli piace, nella sezione "W3Schools is trouble", nessuna delle tre ragioni che danno hanno a che fare con informazioni imprecise. Non hanno un solo esempio di qualcosa che sia effettivamente "sbagliato". I loro reclami sono che non affermano esplicitamente di non essere affiliati a w3, fanno pagare per le certificazioni non riconosciute e non si aggiornano rapidamente con nuovi contenuti (ad esempio HTML 5).
Matteo

10
@Matthew, Informazioni obsolete, in linguaggi delicati come Javascript, SQL o PHP, sono ciò che guida le masse di aspiranti programmatori ad attenersi a tecnologie vecchie e potenzialmente pericolose (come l' mysql_estensione di PHP) di cui il flusso di domande SO è solo un esempio. IIRC ci sono stati anche degli errori molto sottili nella sezione SQL, ma è passato quasi un anno dall'ultima volta che ho visitato il sito Web e molti di essi potrebbero anche essere riparati. E anche se tutto quanto sopra fosse perfetto, non promuoverei comunque un sito Web che tenta di ingannare le persone con la frode del loro certificato.
Scarpa

4
certificazioni losche a parte, è una discreta risorsa di riferimento ed è controproducente per il punto in cui SO deve aggirare denunciandole.
worc,

Risposte:


383

Utilizzando setIntervalosetTimeout

È necessario passare un riferimento a una funzione come primo argomento per setTimeouto setInterval. Questo riferimento può essere sotto forma di:

  • Una funzione anonima

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Un nome di una funzione esistente

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Una variabile che punta a una funzione esistente

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

    Si noti che ho impostato "variabile in una funzione" separatamente da "nome della funzione". Non è evidente che le variabili e i nomi delle funzioni occupino lo stesso spazio dei nomi e possano intasarsi a vicenda.

Passare argomenti

Per chiamare una funzione e passare parametri, è possibile chiamare la funzione all'interno del callback assegnato al timer:

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

Esiste un altro metodo per passare argomenti nel gestore, tuttavia non è compatibile con più browser .

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

Contesto di richiamata

Per impostazione predefinita, il contesto del callback (il valore thisall'interno della funzione chiamata dal timer) quando eseguito è l'oggetto globale window. Se vuoi cambiarlo, usa bind.

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

Sicurezza

Sebbene sia possibile, non dovresti passare una stringa a setTimeouto setInterval. Il passaggio di una stringa rende setTimeout()o setInterval()utilizza una funzionalità simile a eval()quella che esegue le stringhe come script , rendendo possibile l'esecuzione di script arbitraria e potenzialmente dannosa.


ho imparato che quando stai usando solo il nome della funzione la funzione viene copiata, quindi perché stai dicendo al tuo primo esempio che setTumeout foo (funzione) passa il riferimento alla funzione che ho appoggiato viene copiata. e puoi farmi di più per favore sull'eval, per favore.
user1316123

42
Le funzioni di @ user1316123 non vengono mai copiate. lo stesso con oggetti e matrici. sono passati per riferimento . dovresti smettere di leggere w3schools. stanno facendo più male che bene
Joseph,

4
Le funzioni di @JosephtheDreamer sono oggetti. "Un nome di funzione" e "Una variabile che fa riferimento a una funzione" è la stessa cosa. Inoltre, puoi passare i parametri a setTimeout direttamente (non è necessario racchiuderlo in un lambda per esso (anche se come hai detto - browser più recenti). Inoltre, il problema non è quello di consentire agli utenti di eseguire script (possono sempre farlo comunque), è accettando input da altri utenti e l'esecuzione che come sceneggiatura l'utente si può sempre e solo aprire la console ed eseguire arbitrario JavaScript..
Benjamin Gruenbaum

@BenjaminGruenbaum Stavo per fare un commento quasi identico alla tua seconda frase. Ridi :)
ErikE

2
Non avevo capito che dovevi usare una funzione per setTimeout per funzionare correttamente. Grazie per averlo chiarito.
Matt Dell

3

penso che la funzione setTimeout che scrivi non sia in esecuzione. se usi jquery, puoi farlo funzionare correttamente facendo questo:

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });

penso proprio come te ma il link w3schools.com/js/js_timing.asp che dice qualcos'altro
user1316123

se capisco correttamente quando utilizzo le parentesi posso fare riferimento solo alla funzione che contiene il metodo setTimeout perché la funzione Disponibile tra parentesi solo nell'ambito locale?
user1316123

2

Totalmente d'accordo con Joseph.

Ecco un violino per testare questo: http://jsfiddle.net/nicocube/63s2s/

Nel contesto del violino, l'argomento stringa non funziona, secondo me perché la funzione non è definita nell'ambito globale.


w3schools.com/js/js_timing.asp se puoi inserire il link per favore e vedi perché Joseph dice che è pericoloso ma se inserisci il link funziona
user1316123

ragazzi per favore guardate questo: quirksmode.org/js/this.html questo link dice che una funzione può essere copiata
user1316123

Sì, perché le funzioni sono oggetti in JS. Il problema con eval è che valuterà nel contesto globale e non riuscirà a ottenere il contesto locale che si verifica con un violino.
Nicocube,

puoi spiegare in alcune parole su eval per favore.
user1316123


1

Cosa succede nella realtà nel caso in cui passi la stringa come primo parametro della funzione

setTimeout ( 'string', number)

è il valore del primo parametro ottenuto quando è il momento di eseguire (dopo che sono numberpassati i millisecondi). Fondamentalmente è uguale a

setTimeout ( eval('string'), number)

Questo è

una sintassi alternativa che consente di includere una stringa anziché una funzione, che viene compilata ed eseguita alla scadenza del timer. Questa sintassi non è consigliata per gli stessi motivi che rendono l'utilizzo di eval () un rischio per la sicurezza.

Quindi i campioni a cui fai riferimento non sono buoni esempi e possono essere dati in contesti diversi o semplicemente in un semplice errore di battitura.

Se invochi in questo modo setTimeout(something, number), il primo parametro non è stringa, ma puntatore a qualcosa chiamato something. E ancora se somethingè stringa - allora verrà valutata. Ma se è una funzione, la funzione verrà eseguita. campione jsbin


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.

-1

Con le parentesi:

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

Senza virgolette e parentesi:

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

E il terzo utilizza solo le virgolette:

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);

Nell'esempio precedente, la prima funzione di alertMsg2 () chiama immediatamente (diamo il timeout 4S ma non dà fastidio) dopo che alertMsg1 () (un tempo di attesa di 2 secondi) quindi alertMsg4 () (un tempo di attesa di 8 secondi) ma alertMsg3 () non funziona perché lo inseriamo tra virgolette senza parti, quindi viene trattato come una stringa.


Dimostra gli scenari di cui l'interrogatore chiede, ma in realtà non risponde alla domanda. Non vedo cosa si aggiunge alle risposte esistenti di 6 anni .
Stephen P
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.