Różnica między setTimeout z cytatami i nawiasami i bez nich

240

Uczę się JavaScript i ostatnio dowiedziałem się o zdarzeniach JavaScript. Kiedy dowiedziałem się o setTimeoutco W3Schools , zauważyłem dziwną postać, która nie uruchamiać się wcześniej. Używają podwójnych cudzysłowów, a następnie wywołują funkcję.

Przykład:

setTimeout("alertMsg()", 3000);

Wiem, że podwójne i pojedyncze cudzysłowy w JavaScript oznaczają ciąg znaków.

Widziałem też, że mogę zrobić to samo:

setTimeout(alertMsg, 3000);

Z nawiasami, do których się odnosi, bez nawiasów jest kopiowany. Kiedy używam cytatów i nawiasów, robi się szalony.

Będę zadowolony, jeśli ktoś może wyjaśnić mi różnicę między tymi trzema sposobami użycia setTimeout:

Z nawiasami:

setTimeout("alertMsg()", 3000);

Bez cytatów i nawiasów:

setTimeout(alertMsg, 3000);

A trzeci używa tylko cudzysłowów:

setTimeout("alertMsg", 3000);

Uwaga: Lepszym źródłem setTimeoutodniesienia będzie MDN .

użytkownik1316123
źródło
5
@Jefffrey, że witryna w3fools nie twierdzi, że treść jest błędna, tylko że może być nieaktualna i może nie zawierać niektórych nowszych rzeczy. Powinno być przydatne jako odniesienie do (lub do nauki) podstawowych rzeczy. Rozumiem, że ludzie są sfrustrowani tym, że starają się wyglądać, jakby byli częścią W3, ale to nie umniejsza treści. Jest ładnie rozplanowany i łatwy do odczytania z jasnymi przykładami, idealny dla noobów.
Matthew
14
@Matthew „Uważamy jednak, że W3Schools szkodzi społeczności niedokładnymi informacjami”. - w pierwszych trzech wierszach.
But
1
@Jefffrey tak, widziałem to, ale poniżej, gdzie wyjaśniają, co im się nie podoba, w sekcji „W3Schools to problem”, żaden z trzech powodów, które podają, nie ma nic wspólnego z niedokładnymi informacjami. Nie mają ani jednego przykładu czegoś, co faktycznie byłoby „złe”. Ich skargi są takie, że nie mówią wprost, że nie są powiązani z w3, pobierają opłaty za nierozpoznane certyfikaty i nie aktualizują się szybko o nowe treści (np. HTML 5).
Matthew
10
@Matthew, Nieaktualne informacje, w delikatnych językach, takich jak JavaScript, SQL lub PHP, kierują masy początkujących programistów do korzystania ze starych i potencjalnie niebezpiecznych technologii (takich jak mysql_rozszerzenie PHP), których strumień pytań SO jest tylko przykładem. IIRC wystąpiły również bardzo subtelne błędy w sekcji SQL, ale minął prawie rok od ostatniej wizyty na stronie i wiele z nich może być naprawionych. I nawet jeśli wszystko powyższe byłoby idealne, nadal nie promowałbym strony internetowej, która próbuje oszukać ludzi za pomocą oszustwa związanego z ich certyfikatem.
But
4
pomijając podejrzane certyfikaty, jest to przyzwoity zasób referencyjny i przynosi efekt przeciwny do punktu widzenia SO, aby je potępić.
worc,

Odpowiedzi:

382

Za pomocą setIntervallubsetTimeout

Powinieneś przekazać odwołanie do funkcji jako pierwszy argument dla setTimeoutlub setInterval. Odniesienie to może mieć postać:

  • Anonimowa funkcja

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Nazwa istniejącej funkcji

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Zmienna wskazująca na istniejącą funkcję

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

    Zauważ, że ustawiam „zmienną w funkcji” oddzielnie od „nazwy funkcji”. Nie jest oczywiste, że nazwy zmiennych i funkcji zajmują tę samą przestrzeń nazw i mogą się wzajemnie blokować.

Przekazywanie argumentów

Aby wywołać funkcję i przekazać parametry, możesz wywołać funkcję wewnątrz wywołania zwrotnego przypisanego do timera:

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

Istnieje inna metoda przekazywania argumentów do modułu obsługi, jednak nie jest on zgodny z różnymi przeglądarkami .

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

Kontekst oddzwaniania

Domyślnie kontekst wywołania zwrotnego (wartość thisfunkcji wywoływanej przez stoper) podczas wykonywania jest obiektem globalnym window. Jeśli chcesz to zmienić, użyj bind.

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

Bezpieczeństwo

Chociaż jest to możliwe, nie należy przekazywać łańcucha do setTimeoutlub setInterval. Przechodząc ciąg sprawia, setTimeout()lub setInterval()użyć funkcji podobnej do eval()że wykonuje ciągi jako skrypty , czyniąc wykonanie arbitralny i potencjalnie szkodliwy skrypt możliwe.

Joseph
źródło
Dowiedziałem się, że gdy używasz tylko nazwy funkcji, funkcja jest kopiowana, więc dlaczego mówisz na pierwszym przykładzie, że referencja ft setTumeout (funkcja) została skopiowana, funkcja została pochylona. i czy możesz mnie podnieść bardziej proszę o eval, proszę.
użytkownik1316123,
41
Funkcje @ user1316123 nigdy nie są kopiowane. to samo z obiektami i tablicami. są przekazywane przez odniesienie . powinieneś przestać czytać w3schools. wyrządzają więcej szkody niż pożytku
Joseph
4
Funkcje @JosephtheDreamer obiektami. „Nazwa funkcji” i „Zmienna odnosząca się do funkcji” to to samo . Ponadto możesz przekazać parametry do setTimeout bezpośrednio (nie musisz zawijać dla niego lambda (chociaż, jak powiedziałeś - nowsze przeglądarki). Problemem nie jest też umożliwienie użytkownikom wykonywania skryptów (zawsze mogą to zrobić), to przyjmując wejście od innych użytkowników i działa to jak scenariusz sami użytkownik zawsze może po prostu otworzyć konsolę i wykonać dowolny JavaScript..
Benjamin Gruenbaum
@BenjaminGruenbaum Już miałem prawie identyczny komentarz do twojego drugiego zdania. Śmiej się :)
ErikE
2
Nie zdawałem sobie sprawy, że musisz użyć funkcji, aby setTimeout działał poprawnie. Dzięki za wyjaśnienie.
Matt Dell,
3

myślę, że funkcja setTimeout, którą piszesz, nie jest uruchamiana. jeśli używasz jquery, możesz ustawić, aby działała poprawnie, wykonując następujące czynności:

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });
Acil Az
źródło
myślę Tak jak ty, ale link w3schools.com/js/js_timing.asp mówi, że coś innego
1316123,
jeśli dobrze rozumiem, gdy używam nawiasów, mogę odwoływać się tylko do funkcji zawierającej metodę setTimeout, ponieważ funkcja dostępna jest w nawiasach tylko w jej zasięgu lokalnym?
użytkownik1316123,
2

Całkowicie zgadzam się z Józefem.

Oto skrzypce, aby to przetestować: http://jsfiddle.net/nicocube/63s2s/

W kontekście skrzypce argument string nie działa, moim zdaniem, ponieważ funkcja nie jest zdefiniowana w zasięgu globalnym.

Nicocube
źródło
w3schools.com/js/js_timing.asp jeśli możesz wprowadzić link, proszę zobacz, ponieważ Joseph mówi, że jest niebezpieczny, ale jeśli podasz link działa
użytkownik1316123
chłopaki, proszę spojrzeć na to: quirksmode.org/js/this.html ten link mówi, że func można skopiować
1316123,
Tak, ponieważ funkcje są obiektami w JS. Problem z eval polega na tym, że będzie ewaluował w kontekście globalnym i nie uzyska lokalnego kontekstu, który pojawia się przy skrzypcach.
Nicocube,
czy możesz wyjaśnić kilka słów o eval, proszę.
user1316123
1

Co dzieje się w rzeczywistości w przypadku podania ciągu jako pierwszego parametru funkcji

setTimeout ( 'string', number)

jest oceniana wartość pierwszego parametru, kiedy nadszedł czas uruchomienia (po upływie numbermilisekund). Zasadniczo jest to równe

setTimeout ( eval('string'), number)

To jest

alternatywna składnia, która pozwala dołączyć ciąg zamiast funkcji, która jest kompilowana i wykonywana po upływie czasu. Ta składnia nie jest zalecana z tych samych powodów, które sprawiają, że używanie eval () stanowi zagrożenie bezpieczeństwa.

Próbki, do których się odwołujesz, nie są dobrymi próbkami i mogą być podane w innym kontekście lub po prostu literówką.

Jeśli wywołujesz w ten sposób setTimeout(something, number), pierwszym parametrem nie jest ciąg, ale wskaźnik do czegoś zwanego something. I znowu, jeśli somethingjest ciągiem - wtedy zostanie to ocenione. Ale jeśli jest to funkcja, funkcja zostanie wykonana. próbka jsbin

Witalij Markitanow
źródło
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
źródło
-1

Z nawiasami:

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

Bez cytatów i nawiasów:

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

A trzeci używa tylko cudzysłowów:

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

W powyższym przykładzie pierwsze wywołanie funkcji alertMsg2 () następuje natychmiast (dajemy limit czasu 4S, ale nie przeszkadza) po tym alertMsg1 () (czas oczekiwania 2 sekundy), a następnie alertMsg4 () (czas oczekiwania 8 sekund) ale alertMsg3 () nie działa, ponieważ umieszczamy go w cudzysłowie bez stron, więc jest traktowany jako ciąg.

Srikrushna
źródło
Demonstruje scenariusze, o które pyta pytający, ale tak naprawdę nie odpowiada na pytanie. Nie rozumiem, co to dodaje do istniejących 6-letnich odpowiedzi.
Stephen P