Різниця між setTimeout з лапками і без дужок


240

Я вивчаю JavaScript, і нещодавно дізнався про події в часі JavaScript. Коли я дізнався про setTimeoutв W3Schools , я помітив дивну фігуру , яку я не біжіть в раніше. Вони використовують подвійні лапки, а потім викликають функцію.

Приклад:

setTimeout("alertMsg()", 3000);

Я знаю, що подвійні та одиничні лапки в JavaScript означають рядок.

Також я побачив, що я можу зробити те саме, що:

setTimeout(alertMsg, 3000);

З дужками він посилається, без скобок скопіюється. Коли я використовую лапки та дужки, це стає божевільним.

Я буду радий, якщо хтось може пояснити мені різницю між цими трьома способами використання setTimeout:

З дужками:

setTimeout("alertMsg()", 3000);

Без лапок і дужок:

setTimeout(alertMsg, 3000);

І третє - це лише використання лапок:

setTimeout("alertMsg", 3000);

NB: Кращим джерелом для setTimeoutдовідки буде MDN .


5
@Jefffrey, що веб-сайт w3fools не говорить про те, що вміст там неправильний, а лише те, що він може бути застарілим, а деякі нові речі відсутні. Має бути добре, щоб використовувати в якості посилання на (або вивчити) основні речі. Я можу зрозуміти, що люди засмучені тим, як вони намагаються здаватися, що вони є частиною w3, але це не шкодить вмісту. Це добре викладене і легко читати з чіткими прикладами, префект для нуб.
Матвій

14
@Matthew "Ми вважаємо, що W3Schools завдає шкоди громаді недостовірною інформацією". - в межах перших трьох рядків.
взуття

1
@ Джеффрі Так, я бачив це, але нижче, де вони пояснюють, що їм не подобається в цьому, у розділі "W3Schools - це біда", жодна з трьох причин, які вони дають, не має нічого спільного з неточною інформацією. У них немає жодного прикладу нічого, що насправді є "неправильним". Їх скарги полягають у тому, що вони прямо не заявляють, що вони не пов'язані з w3, вони стягують плату за нерозпізнані сертифікати і не швидко оновлюються новим вмістом (наприклад, html 5).
Матвій

10
@Matthew, застаріла інформація, на делікатних мовах, таких як Javascript, SQL або PHP, - це те, що керує масою прагне програмістів дотримуватися старих і потенційно небезпечних технологій (наприклад, mysql_розширення PHP), з яких потік запитань SO є лише прикладом. IIRC також було кілька тонких помилок і в розділі SQL, але минуло майже рік з моменту останнього відвідування веб-сайту, і багато з них можуть бути виправлені. І навіть якби все вище було ідеальним, я все одно не просував би веб-сайт, який намагається обдурити людей своїм шахрайством.
взуття

4
тіньові сертифікати осторонь, це гідний довідковий ресурс, і контрпродуктивним для всього пункту ЗС є те, щоб обійти денонсування.
worc

Відповіді:


382

Використання setIntervalабоsetTimeout

Вам слід передати посилання на функцію як перший аргумент для setTimeoutабо setInterval. Ця довідка може бути у вигляді:

  • Анонімна функція

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Назва існуючої функції

    function foo(){...}
    
    setTimeout(foo, 2000);
    
  • Змінна, яка вказує на існуючу функцію

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

    Зауважте, що я встановлюю "змінну у функції" окремо від "ім'я функції". Не очевидно, що змінні та назви функцій займають одне і те саме простір імен і можуть заважати один одному.

Передача аргументів

Щоб викликати функцію та передавати параметри, ви можете викликати функцію всередині зворотного дзвінка, призначеного таймеру:

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

Існує ще один метод передачі аргументів в обробник, однак він не сумісний між браузером .

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

Контекст зворотного виклику

За замовчуванням контекст зворотного виклику (значення thisвсередині функції, викликаної таймером), коли виконується, є глобальним об'єктом window. Якщо ви хочете змінити це, скористайтеся bind.

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

Безпека

Хоча це можливо, ви не повинні передавати рядок до setTimeoutабо setInterval. Передавання рядка робить setTimeout()або setInterval()використовує функцію, аналогічну eval()тій, що виконує рядки як сценарії , що робить можливим довільне та потенційно шкідливе виконання сценарію.


я дізнався, що коли ви використовуєте лише ім'я функції, функція копіюється, тому чому ви говорите на своєму першому прикладі, що параметр setTumeout foo (функція) передає посилання, функція, яку я нахилила, копіюється. і чи можете ви мені більше сказати, будь ласка, про eval будь ласка.
user1316123

41
@ user1316123 функції ніколи не копіюються. те саме з об'єктами та масивами. вони передаються шляхом посилання . ви повинні перестати читати w3schools. вони роблять більше шкоди, ніж користі
Йосип

4
@JosephtheDreamer - це об'єкти. "Ім'я функції" та "Змінна, яка посилається на функцію" - це те саме. Крім того, ви можете передавати параметри setTimeout безпосередньо (для цього не потрібно загортати лямбда (хоча, як ви сказали - новіші браузери). Проблема також не в тому, щоб користувачі могли виконувати сценарії (вони завжди можуть це робити), це, приймаючи дані від інших користувачів і запускаючи це як сценарій. Користувач сам завжди може просто відкрити консоль і виконати довільний JavaScript.
Benjamin Gruenbaum

@BenjaminGruenbaum Я збирався зробити майже однаковий коментар до вашого другого речення. Смійся :)
ЕрікЕ

2
Я не усвідомлював, що вам потрібно правильно використовувати функцію setTimeout. Дякуємо, що очистили це.
Метт Делл

3

Я думаю, що функція setTimeout, яку ви пишете, не виконується. якщо ви використовуєте jquery, ви можете змусити його запустити правильно:

    function alertMsg() {
      //your func
    }

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

Я думаю, як і ти, але посилання w3schools.com/js/js_timing.asp кажучи про щось інше
user1316123

якщо я правильно розумію, коли я використовую дужки, я можу посилатися лише на функцію, яка містить метод setTimeout, оскільки функція доступна в дужках лише в локальній області застосування?
user1316123

2

Повністю згоден з Йосифом.

Ось загадка для перевірки цього: http://jsfiddle.net/nicocube/63s2s/

У контексті загадки, аргумент рядка не працює, на мою думку, тому що функція не визначена в глобальній області.


w3schools.com/js/js_timing.asp, якщо ви можете перейти за посиланням, будь ласка, дивіться, бо Джозеф каже, що це небезпечно, але якщо ви введете посилання його працює
user1316123

хлопці, будь ласка, подивіться на це: quirksmode.org/js/this.html в цьому посиланні сказано, що функцію можна скопіювати
user1316123

Так, це може, тому що функції є об'єктом в JS. Проблема з eval полягає в тому, що він буде оцінюватися в глобальному контексті, і не зможе отримати локальний контекст, який виникає з загадкою.
Нікокуб

чи можете ви поясніть якимись словами про eval будь ласка.
user1316123


1

Що відбувається насправді, якщо ви передаєте рядок як перший параметр функції

setTimeout ( 'string', number)

Значення першого парамуму було оцінено, коли настає час запуску (після numberпроходження мілісекунд). В основному він дорівнює

setTimeout ( eval('string'), number)

Це

альтернативний синтаксис, який дозволяє включати рядок замість функції, яка компілюється та виконується, коли термін дії таймера закінчується. Цей синтаксис не рекомендується з тих же причин, що створюють ризик безпеки eval ().

Тож зразки, на які ви посилаєтесь, не є хорошими зразками, і їх можна давати в іншому контексті або просто просто друкувати.

Якщо ви посилаєтесь так setTimeout(something, number), перший параметр - це не рядок, а вказівник на щось, що називається something. І знову, якщо somethingрядок - це буде оцінено. Але якщо це функція, то функція буде виконуватися. зразок 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

З дужками:

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

Без лапок і дужок:

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

І третє - це лише використання лапок:

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

У наведеному вище прикладі спочатку функція alarMsg2 () викликає негайно (ми даємо час виходу 4S, але це не турбує) після цього alertMsg1 () (час очікування 2 секунди), а потім alertMsg4 () (час очікування 8 секунди) але alertMsg3 () не працює, тому що ми розміщуємо його в лапках без партій, тому він трактується як рядок.


Демонструє сценарії, про які питає запитуючий, але насправді не відповідає на питання. Я не бачу, що це додає до наявних шестирічних відповідей.
Stephen P
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.