Perbedaan antara setTimeout dengan dan tanpa tanda kutip dan tanda kurung

241

Saya belajar JavaScript dan saya baru-baru ini belajar tentang peristiwa waktu JavaScript. Ketika saya belajar tentang setTimeoutdi W3Schools , saya melihat sosok aneh yang tidak saya temui sebelumnya. Mereka menggunakan tanda kutip ganda dan kemudian memanggil fungsinya.

Contoh:

setTimeout("alertMsg()", 3000);

Saya tahu bahwa tanda kutip ganda dan tunggal dalam JavaScript berarti string.

Saya juga melihat bahwa saya dapat melakukan hal yang sama seperti itu:

setTimeout(alertMsg, 3000);

Dengan tanda kurung itu merujuk, tanpa tanda kurung itu disalin. Ketika saya menggunakan tanda kutip dan tanda kurung itu menjadi gila.

Saya akan senang jika seseorang dapat menjelaskan kepada saya perbedaan antara tiga cara menggunakan ini setTimeout:

Dengan tanda kurung:

setTimeout("alertMsg()", 3000);

Tanpa tanda kutip dan tanda kurung:

setTimeout(alertMsg, 3000);

Dan yang ketiga hanya menggunakan tanda kutip:

setTimeout("alertMsg", 3000);

NB: Sumber setTimeoutreferensi yang lebih baik adalah MDN .

pengguna1316123
sumber
5
@ JeffFrey bahwa situs web w3fools tidak mengatakan bahwa konten di sana salah, hanya saja mungkin sudah ketinggalan zaman dan kehilangan beberapa hal baru. Harus baik-baik saja untuk digunakan sebagai referensi untuk (atau belajar) hal-hal inti. Saya dapat memahami orang-orang yang frustrasi dengan cara mereka berusaha terlihat seperti mereka bagian dari w3, tetapi itu tidak mengurangi kontennya. Ini ditata dengan baik dan mudah dibaca dengan contoh yang jelas, prefek untuk noobs.
Matius
14
@Matthew "Namun, kami merasa bahwa W3Schools merugikan komunitas dengan informasi yang tidak akurat." - dalam tiga baris pertama.
Sepatu
1
@ Jeffffrey ya saya melihat itu, tetapi di bagian bawah di mana mereka menjelaskan apa yang tidak mereka sukai tentang itu, di bagian "W3Schools is trouble", tidak satu pun dari tiga alasan yang mereka berikan ada hubungannya dengan informasi yang tidak akurat. Mereka tidak memiliki satu contoh pun dari apa pun yang sebenarnya "salah". Keluhan mereka adalah bahwa mereka tidak secara eksplisit mengatakan bahwa mereka tidak berafiliasi dengan w3, mereka mengenakan biaya untuk sertifikasi yang tidak diakui, dan mereka tidak memperbarui dengan cepat dengan konten baru (misalnya html 5).
Matius
10
@Matthew, Informasi kedaluwarsa, dalam bahasa yang rumit seperti Javascript, SQL atau PHP, adalah apa yang memandu massa calon programmer untuk tetap berpegang pada teknologi lama dan berpotensi berbahaya (seperti mysql_ekstensi PHP) di mana aliran pertanyaan SO hanyalah sebuah contoh. IIRC ada beberapa kesalahan yang sangat halus di bagian SQL juga, tapi sudah hampir setahun sejak terakhir kali saya mengunjungi situs web dan banyak dari mereka mungkin juga diperbaiki. Dan bahkan jika semua di atas sempurna saya masih tidak akan mempromosikan situs web yang mencoba menipu orang dengan penipuan sertifikat mereka.
Sepatu
4
selain sertifikasi teduh, ini adalah sumber referensi yang layak dan itu kontraproduktif ke seluruh titik SO untuk berkeliling mencela mereka.
worc

Jawaban:

383

Menggunakan setIntervalatausetTimeout

Anda harus memberikan referensi ke fungsi sebagai argumen pertama untuk setTimeoutatau setInterval. Referensi ini dapat berupa:

  • Fungsi anonim

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Nama fungsi yang ada

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Variabel yang menunjuk ke fungsi yang ada

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

    Perhatikan bahwa saya mengatur "variabel dalam suatu fungsi" secara terpisah dari "nama fungsi". Tidak jelas bahwa variabel dan nama fungsi menempati namespace yang sama dan dapat saling mengalahkan.

Melewati argumen

Untuk memanggil suatu fungsi dan melewatkan parameter, Anda dapat memanggil fungsi di dalam callback yang ditugaskan ke penghitung waktu:

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

Ada metode lain untuk meneruskan argumen ke dalam handler, namun itu tidak kompatibel lintas-browser .

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

Konteks panggilan balik

Secara default, konteks panggilan balik (nilai thisdi dalam fungsi yang disebut oleh timer) ketika dieksekusi adalah objek global window. Jika Anda ingin mengubahnya, gunakan bind.

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

Keamanan

Meskipun mungkin, Anda tidak boleh melewatkan string ke setTimeoutatau setInterval. Melewati string membuat setTimeout()atau setInterval()menggunakan fungsi yang mirip dengan eval()yang mengeksekusi string sebagai script , membuat sewenang-wenang dan berpotensi membahayakan eksekusi script mungkin.

Yusuf
sumber
saya telah belajar bahwa ketika Anda hanya menggunakan nama fungsi fungsi disalin jadi mengapa Anda mengatakan pada contoh pertama Anda bahwa setTumeout foo (fungsi) lulus referensi fungsi yang saya bersandar disalin. dan bisakah kamu lebih menghargai aku, tolong tentang eval.
user1316123
42
Fungsi @ user1316123 tidak pernah disalin. sama dengan objek dan array. mereka dilewatkan dengan referensi . Anda harus berhenti membaca w3schools. mereka melakukan lebih banyak kerusakan daripada kebaikan
Joseph
4
Fungsi @JosephtheDreamer adalah objek. "Nama fungsi" dan "Variabel yang merujuk ke fungsi" adalah hal yang sama . Juga, Anda dapat mengirimkan parameter ke setTimeout secara langsung (tidak perlu membungkus lambda untuk itu (meskipun seperti yang Anda katakan - browser yang lebih baru). Juga, masalahnya bukan dengan membiarkan pengguna mengeksekusi skrip (mereka tetap dapat melakukan hal ini), itu dengan menerima masukan dari lainnya pengguna dan menjalankan bahwa sebagai script pengguna sendiri dapat selalu hanya membuka konsol dan mengeksekusi sewenang-wenang JavaScript..
Benjamin Gruenbaum
@BenjaminGruenbaum Saya baru saja akan membuat komentar yang hampir sama dengan kalimat kedua Anda. Tertawa :)
ErikE
2
Saya tidak menyadari Anda perlu menggunakan fungsi untuk setTimeout agar berfungsi dengan benar. Terima kasih sudah membereskannya.
Matt Dell
3

saya pikir fungsi setTimeout yang Anda tulis tidak dijalankan. jika Anda menggunakan jquery, Anda dapat membuatnya berjalan dengan benar dengan melakukan ini:

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });
Acil Az
sumber
i thinkink Sama seperti Anda tetapi tautan w3schools.com/js/js_timing.asp mengatakan somting lain
user1316123
jika saya mengerti dengan benar ketika saya menggunakan tanda kurung saya dapat merujuk hanya ke fungsi yang berisi metode setTimeout karena fungsi yang tersedia di tanda kurung hanya di lingkup lokal saja?
user1316123
2

Sepenuhnya setuju dengan Joseph.

Berikut ini biola untuk menguji ini: http://jsfiddle.net/nicocube/63s2s/

Dalam konteks biola, argumen string tidak berfungsi, menurut saya karena fungsinya tidak didefinisikan dalam lingkup global.

Nicocube
sumber
w3schools.com/js/js_timing.asp jika Anda dapat memasukkan tautan, silakan dan lihat karena Joseph mengatakan itu berbahaya tetapi jika Anda memasukkan tautan itu berfungsi
user1316123
guys tolong lihat ini: quirksmode.org/js/this.html tautan ini mengatakan bahwa func dapat disalin
user1316123
Ya itu bisa, karena fungsi adalah objek di JS. Masalah dengan eval adalah ia akan eval dalam konteks global, dan gagal mendapatkan konteks lokal yang terjadi dengan biola.
Nicocube
tolong jelaskan dalam beberapa kata tentang eval.
user1316123
Beberapa penjelasan yang baik: javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval
Nicocube
1

Apa yang terjadi dalam kenyataan jika Anda melewatkan string sebagai parameter fungsi pertama

setTimeout ( 'string', number)

adalah nilai param pertama yang dievaluasi ketika saatnya untuk dijalankan (setelah numbermilidetik berlalu). Pada dasarnya itu sama dengan

setTimeout ( eval('string'), number)

Ini adalah

sintaksis alternatif yang memungkinkan Anda untuk memasukkan string alih-alih fungsi, yang dikompilasi dan dieksekusi ketika timer berakhir. Sintaks ini tidak direkomendasikan untuk alasan yang sama yang membuat menggunakan eval () risiko keamanan.

Jadi sampel yang Anda referensikan bukan sampel yang baik, dan dapat diberikan dalam konteks yang berbeda atau hanya kesalahan ketik sederhana.

Jika Anda memanggil seperti ini setTimeout(something, number), parameter pertama bukan string, tetapi penunjuk ke sesuatu yang disebut something. Dan lagi jika somethingstring - maka akan dievaluasi. Tetapi jika itu adalah fungsi, maka fungsi akan dieksekusi. sampel jsbin

Vitaliy Markitanov
sumber
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
sumber
-1

Dengan tanda kurung:

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

Tanpa tanda kutip dan tanda kurung:

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

Dan yang ketiga hanya menggunakan tanda kutip:

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

Dalam contoh di atas, pertama alertMsg2 () segera memanggil fungsi (kami memberikan waktu keluar 4S tetapi tidak mengganggu) setelah itu alertMsg1 () (Waktu tunggu 2 Detik) lalu alertMsg4 () (Waktu tunggu 8 Detik) tetapi alertMsg3 () tidak berfungsi karena kami menempatkannya di dalam tanda kutip tanpa pihak sehingga diperlakukan sebagai string.

Srikrushna
sumber
Peragakan skenario yang ditanyakan oleh penanya, tetapi tidak benar-benar menjawab pertanyaan. Saya tidak melihat apa yang ditambahkan dari jawaban 6 tahun yang ada .
Stephen P