包含和不包含引号和括号的setTimeout之间的区别


240

我正在学习JavaScript,最近又了解了JavaScript计时事件。当我setTimeoutW3Schools学习时,我注意到一个我从未遇到过的奇怪人物。他们使用双引号,然后调用该函数。

例:

setTimeout("alertMsg()", 3000);

我知道JavaScript中的双引号和单引号表示字符串。

我也看到我可以做这样的事情:

setTimeout(alertMsg, 3000);

有括号的是指,没有括号的是复制的。当我使用引号和括号时,它变得很疯狂。

如果有人可以向我解释这三种使用方式之间的区别,我将感到非常高兴setTimeout

加上括号:

setTimeout("alertMsg()", 3000);

没有引号和括号:

setTimeout(alertMsg, 3000);

第三只使用引号:

setTimeout("alertMsg", 3000);

注意:MDNsetTimeout是更好的参考来源。


5
w3fools网站的@Jefffrey并没有说那里的内容是错误的,只是说它可能已经过时并丢失了一些较新的内容。可以很好地用作核心知识的参考(或学习)。我能理解人们对他们看起来像是w3的一部分感到沮丧,但这并没有减损其内容。布局合理,易于阅读,带有清晰示例,是菜鸟的完美选择。
马修(Matthew)

14
@Matthew“不过,我们认为W3Schools正在使用不正确的信息来损害社区。” -在前三行中。
Shoe

1
@Jefffrey是的,我看到了,但是请在“ W3Schools遇到麻烦”部分中向下解释他们不满意的内容,这三个原因均与错误信息无关。他们没有任何一个真正“错误”的例子。他们的抱怨是他们没有明确表示他们与w3不隶属,他们为无法识别的证书收费,并且没有以新内容(例如html 5)快速更新。
马修,

10
@Matthew,用Javascript,SQL或PHP等精致语言编写的过时信息,引导有志向往的程序员坚持使用古老而潜在的危险技术(例如mysql_PHP 的扩展),其中SO问题流只是一个例子。IIRC在SQL部分中也存在一些非常微妙的错误,但是距我上次访问该网站已经快一年了,而且很多错误也可能会得到解决。即使以上所有内容都很完美,我也不会推广任何试图欺骗其证书欺诈行为的网站。
2013年

4
除了可疑的认证,它是一个不错的参考资源,并且对SO进行谴责的整个观点都适得其反。
worc 2013年

Answers:


382

使用setIntervalsetTimeout

您应该传递对函数的引用作为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计时器调用的函数内部的值)为global object window。如果要更改它,请使用bind

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

安全

尽管有可能,但您不应将字符串传递setTimeoutsetInterval。传递字符串使setTimeout()setInterval()使用类似于将字符串作为脚本执行的功能,从而eval()可以执行任意的且可能有害的脚本。


我了解到,当您仅使用函数名称时,将复制该函数,因此,为什么要在第一个示例中说setTumeout foo(函数)传递引用将复制我倾斜的函数。能否请我给我更高的评估价?
user1316123

41
永远不会复制@ user1316123函数。与对象和数组相同。它们通过引用传递。您应该停止阅读w3schools。他们的弊大于利
约瑟夫

4
@JosephtheDreamer函数对象。“函数名称”和“引用函数的变量”是一回事。另外,您可以直接向setTimeout传递参数(无需包装lambda(尽管就像您说的那样-新型浏览器)。此外,问题不在于让用户执行脚本(他们始终可以执行此操作),它是由接受输入其他用户运行的是作为脚本的用户自己可以永远只是打开控制台,并执行任意JavaScript。
本杰明Gruenbaum

@BenjaminGruenbaum我将对您的第二句话发表几乎相同的评论。笑:)
ErikE

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 2012年

如果我在使用方括号时正确理解,我只能引用包含setTimeout方法的函数,因为该函数仅在方括号中在本地范围可用?
user1316123

2

完全同意约瑟夫。

这是一个测试这个的小提琴:http : //jsfiddle.net/nicocube/63s2s/

在小提琴音乐中,我认为字符串参数不起作用,因为该函数未在全局范围内定义。


w3schools.com/js/js_timing.asp如果您可以输入链接,然后看看,因为约瑟夫说这很危险,但是如果您输入链接,它可以正常工作
user1316123'4

伙计们,请看这个:quirksmode.org/js/this.html这个链接说可以复制一个func
user1316123'4

是的,可以,因为函数是JS中的对象。eval的问题在于它将在全局上下文中进行评估,而无法获得带有小提琴的局部上下文。
Nicocube 2012年

您能用几个词解释一下评估吗?
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);

在上面的示例中,在该alertMsg1()(等待2秒的时间)之后,首先立即调用alertMsg2()函数(我们给出了超时4S,但它不会打扰),然后又调用alertMsg4()(等待8秒的时间)但是alertMsg3()无法正常工作,因为我们将其放在引号中,没有相关各方,因此将其视为字符串。


演示提问者提出的方案,但实际上并未回答问题。我看不出这与现有的6年历史答案相加了什么。
斯蒂芬·P
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.