Unterschied zwischen setTimeout mit und ohne Anführungszeichen und Klammern


240

Ich lerne JavaScript und habe kürzlich etwas über JavaScript-Timing-Ereignisse gelernt. Als ich setTimeoutbei W3Schools davon erfuhr , bemerkte ich eine seltsame Figur, die ich vorher nicht kennengelernt hatte. Sie verwenden doppelte Anführungszeichen und rufen dann die Funktion auf.

Beispiel:

setTimeout("alertMsg()", 3000);

Ich weiß, dass doppelte und einfache Anführungszeichen in JavaScript eine Zeichenfolge bedeuten.

Ich habe auch gesehen, dass ich das auch so machen kann:

setTimeout(alertMsg, 3000);

Mit den Klammern bezieht es sich, ohne die Klammern wird es kopiert. Wenn ich die Anführungszeichen und Klammern verwende, wird es verrückt.

Ich würde mich freuen, wenn mir jemand den Unterschied zwischen diesen drei Verwendungsmöglichkeiten erklären kann setTimeout:

Mit den Klammern:

setTimeout("alertMsg()", 3000);

Ohne die Anführungszeichen und Klammern:

setTimeout(alertMsg, 3000);

Und der dritte verwendet nur Anführungszeichen:

setTimeout("alertMsg", 3000);

NB: Eine bessere setTimeoutReferenzquelle wäre MDN .


5
@ Jefffrey, dass die w3fools-Website nicht sagt, dass der Inhalt dort falsch ist, nur dass er möglicherweise veraltet ist und einige der neueren Inhalte fehlen. Sollte in Ordnung sein, um als Referenz für das Kernmaterial zu dienen (oder es zu lernen). Ich kann verstehen, dass die Leute frustriert sind, weil sie versuchen, Teil von w3 zu sein, aber das beeinträchtigt den Inhalt nicht. Es ist schön angelegt und leicht zu lesen mit klaren Beispielen, Präfekt für Noobs.
Matthew

14
@Matthew "Wir haben jedoch das Gefühl, dass W3Schools der Community durch ungenaue Informationen Schaden zufügt." - innerhalb der ersten drei Zeilen.
Schuh

1
@ Jefffrey Ja, ich habe das gesehen, aber weiter unten, wo sie erklären, was sie daran nicht mögen, im Abschnitt "W3Schools ist Ärger" hat keiner der drei Gründe, die sie angeben, etwas mit ungenauen Informationen zu tun. Sie haben kein einziges Beispiel für etwas, das tatsächlich "falsch" ist. Ihre Beschwerden sind, dass sie nicht ausdrücklich sagen, dass sie nicht mit w3 verbunden sind, dass sie nicht anerkannte Zertifizierungen in Rechnung stellen und dass sie nicht schnell mit neuen Inhalten (z. B. HTML 5) aktualisieren.
Matthew

10
@Matthew, Veraltete Informationen in heiklen Sprachen wie Javascript, SQL oder PHP führen viele aufstrebende Programmierer dazu, sich an alte und potenziell gefährliche Technologien (wie die mysql_Erweiterung von PHP) zu halten, für die der SO-Fragenstrom nur ein Beispiel ist. IIRC gab es auch einige sehr subtile Fehler im SQL-Bereich, aber es ist fast ein Jahr her, seit ich die Website das letzte Mal besucht habe, und viele davon können auch behoben werden. Und selbst wenn alles oben Genannte perfekt wäre, würde ich keine Website bewerben, die versucht, Menschen mit dem Betrug ihres Zertifikats zu täuschen.
Schuh

4
Abgesehen von zwielichtigen Zertifizierungen ist es eine anständige Referenzressource und es ist kontraproduktiv für SO, sie zu denunzieren.
worc

Antworten:


382

Verwenden von setIntervalodersetTimeout

Sie sollten einen Verweis auf eine Funktion als erstes Argument für setTimeoutoder übergeben setInterval. Diese Referenz kann in Form von:

  • Eine anonyme Funktion

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Ein Name einer vorhandenen Funktion

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Eine Variable, die auf eine vorhandene Funktion verweist

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

    Beachten Sie, dass ich "Variable in einer Funktion" getrennt von "Funktionsname" setze. Es ist nicht ersichtlich, dass Variablen und Funktionsnamen denselben Namespace belegen und sich gegenseitig überladen können.

Argumente übergeben

Um eine Funktion aufzurufen und Parameter zu übergeben, können Sie die Funktion innerhalb des dem Timer zugewiesenen Rückrufs aufrufen:

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

Es gibt eine andere Methode, um Argumente an den Handler zu übergeben, die jedoch nicht browserübergreifend kompatibel ist .

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

Rückrufkontext

Standardmäßig ist der Kontext des Rückrufs (der Wert thisinnerhalb der vom Timer aufgerufenen Funktion) bei der Ausführung das globale Objekt window. Wenn Sie es ändern möchten, verwenden Sie bind.

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

Sicherheit

Obwohl es möglich ist, sollten Sie keine Zeichenfolge an setTimeoutoder übergeben setInterval. String übergeben macht setTimeout()oder setInterval()eine ähnliche Funktionalität wie verwenden , eval()dass ausführt Strings als Skripte , so dass beliebig und potenziell schädliche Skriptausführung möglich.


Ich habe gelernt, dass, wenn Sie nur den Funktionsnamen verwenden, die Funktion kopiert wird. Warum sagen Sie also in Ihrem ersten Beispiel, dass die Passreferenz setTumeout foo (function), die die Funktion, die ich gelehnt habe, kopiert wurde? und kannst du mir bitte mehr über die Bewertung sagen?
user1316123

41
@ user1316123 Funktionen werden niemals kopiert. Gleiches gilt für Objekte und Arrays. Sie werden als Referenz übergeben . Sie sollten aufhören, w3schools zu lesen. Sie tun mehr Schaden als Nutzen
Joseph

4
@ JosephtheDreamer-Funktionen sind Objekte. "Ein Funktionsname" und "Eine Variable, die sich auf eine Funktion bezieht" ist dasselbe . Sie können Parameter auch direkt an setTimeout übergeben (Sie müssen kein Lambda dafür einbinden (obwohl, wie Sie sagten - neuere Browser). Außerdem besteht das Problem nicht darin, dass Benutzer Skripte ausführen können (dies ist ohnehin immer möglich). es ist durch Eingabe von der Annahme anderen Benutzern und ausgeführt , dass als Skript Der Benutzer selbst kann immer nur die Konsole öffnen und willkürliche JavaScript ausführen..
Benjamin Grünbaum

@BenjaminGruenbaum Ich wollte gerade einen fast identischen Kommentar zu Ihrem zweiten Satz abgeben. Lachen :)
ErikE

2
Ich wusste nicht, dass Sie eine Funktion verwenden müssen, damit setTimeout ordnungsgemäß funktioniert. Danke, dass du das geklärt hast.
Matt Dell

3

Ich denke, die setTimeout-Funktion, die Sie schreiben, wird nicht ausgeführt. Wenn Sie jquery verwenden, können Sie es folgendermaßen korrekt ausführen:

    function alertMsg() {
      //your func
    }

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

Ich denke, genau wie Sie, aber der Link w3schools.com/js/js_timing.asp sagt etwas anderes
user1316123

Wenn ich richtig verstehe, wenn ich Klammern verwende, kann ich nur auf die Funktion verweisen, die die setTimeout-Methode enthält, da die Funktion in den Klammern nur im lokalen Bereich verfügbar ist.
user1316123

2

Stimme Joseph vollkommen zu.

Hier ist eine Geige, um dies zu testen: http://jsfiddle.net/nicocube/63s2s/

Im Kontext der Geige funktioniert das String-Argument meiner Meinung nach nicht, da die Funktion nicht im globalen Bereich definiert ist.


w3schools.com/js/js_timing.asp Wenn Sie den Link eingeben können, sehen Sie bitte, weil Joseph sagt, dass es gefährlich ist, aber wenn Sie den Link eingeben, funktioniert es
user1316123

Jungs, bitte schaut euch das an: quirksmode.org/js/this.html Dieser Link sagt, dass eine Funktion kopiert werden kann
user1316123

Ja, das kann es, weil Funktionen in JS Objekte sind. Das Problem bei der Bewertung besteht darin, dass sie im globalen Kontext bewertet wird und keinen lokalen Kontext erhält, der mit einer Geige auftritt.
Nicocube

Kannst du bitte ein paar Worte über eval erklären?
user1316123


1

Was passiert in der Realität, wenn Sie einen String als ersten Funktionsparameter übergeben?

setTimeout ( 'string', number)

Der Wert des ersten Parameters wurde ausgewertet, wenn er ausgeführt werden soll (nach Ablauf der verstrichenen Millisekunden number). Grundsätzlich ist es gleich

setTimeout ( eval('string'), number)

Das ist

Eine alternative Syntax, mit der Sie anstelle einer Funktion eine Zeichenfolge einfügen können, die kompiliert und ausgeführt wird, wenn der Timer abläuft. Diese Syntax wird aus den gleichen Gründen nicht empfohlen, die die Verwendung von eval () zu einem Sicherheitsrisiko machen.

Beispiele, auf die Sie sich beziehen, sind also keine guten Beispiele und können in einem anderen Kontext oder einfach nur als Tippfehler angegeben werden.

Wenn Sie so aufrufen setTimeout(something, number), ist der erste Parameter kein String, sondern ein Zeiger auf etwas, das aufgerufen wird something. Und wieder, wenn somethinges ein String ist, wird er ausgewertet. Wenn es sich jedoch um eine Funktion handelt, wird die Funktion ausgeführt. jsbin Probe


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

Mit den Klammern:

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

Ohne die Anführungszeichen und Klammern:

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

Und der dritte verwendet nur Anführungszeichen:

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

Im obigen Beispiel wird zuerst die Funktion alertMsg2 () sofort aufgerufen (wir geben die Zeitüberschreitung 4S an, aber es stört nicht), danach alertMsg1 () (eine Wartezeit von 2 Sekunden), dann alertMsg4 () (eine Wartezeit von 8 Sekunden) Aber alertMsg3 () funktioniert nicht, weil wir es in die Anführungszeichen ohne Parteien einfügen, sodass es als Zeichenfolge behandelt wird.


Demonstriert die Szenarien, nach denen der Fragesteller fragt, die Frage jedoch nicht beantwortet. Ich sehe nicht, was dies über die vorhandenen 6 Jahre alten Antworten hinzufügt .
Stephen P
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.