带和不带引号和括号的 setTimeout 之间的区别

IT技术 javascript settimeout
2021-01-18 00:54:46

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

例子:

setTimeout("alertMsg()", 3000);

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

我也看到我可以这样做:

setTimeout(alertMsg, 3000);

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

如果有人能向我解释这三种使用方式之间的区别,我会很高兴setTimeout

带括号:

setTimeout("alertMsg()", 3000);

没有引号和括号:

setTimeout(alertMsg, 3000);

第三个是只使用引号:

setTimeout("alertMsg", 3000);

注意:更好的setTimeout参考来源MDN

6个回答

使用setIntervalsetTimeout

您应该传递对函数的引用作为setTimeoutor的第一个参数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);

安全

尽管这是可能的,但您不应将字符串传递setTimeoutsetInterval将字符串传递使setTimeout()setInterval()使用类似的功能eval()执行字符串作为脚本,使得任意的和潜在的有害脚本执行可能的。

@JosephtheDreamer 函数对象。“这指的是函数的变量”,“函数名”,是同样的事情。此外,您可以直接将参数传递给 setTimeout(无需为其包装 lambda(尽管就像您所说的 - 较新的浏览器)。此外,问题不在于让用户执行脚本(无论如何他们总是可以这样做),它是通过接受来自其他用户的输入并将作为脚本运行。用户自己总是可以打开控制台并执行任意 JavaScript。
2021-03-15 00:54:46
我已经了解到,当您仅使用函数名称时,函数会被复制,那么为什么您在第一个示例中说 setTumeout foo(函数)传递引用我倾向于的函数被复制。你能不能给我更多关于 eval 的信息。
2021-03-24 00:54:46
@BenjaminGruenbaum 我正要对你的第二句话发表几乎相同的评论。笑 :)
2021-03-25 00:54:46
我没有意识到您需要使用 setTimeout 函数才能正常工作。感谢您解决这个问题。
2021-03-31 00:54:46
@user1316123 函数永远不会被复制。对象和数组也一样。它们是通过引用传递的你应该停止阅读 w3schools。他们弊大于利
2021-04-03 00:54:46

我认为您编写的 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说 somting else
2021-03-21 00:54:46
如果我在使用括号时理解正确,我只能指包含 setTimeout 方法的函数,因为括号中的函数仅在局部范围内可用?
2021-03-28 00:54:46

完全同意约瑟夫。

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

在小提琴的上下文中,字符串参数不起作用,在我看来,因为该函数未在全局范围内定义。

伙计们请看这个:quirksmode.org/js/this.html这个链接说可以复制一个func
2021-04-02 00:54:46
是的,它可以,因为函数是 JS 中的对象。eval 的问题在于它会在全局上下文中进行 eval,并且无法获取使用 fiddle 发生的本地上下文。
2021-04-02 00:54:46
w3schools.com/js/js_timing.asp如果你能输入链接请看因为约瑟夫说它很危险但是如果你输入链接它的工作
2021-04-05 00:54:46
你能解释一下关于eval的一些话吗?
2021-04-06 00:54:46
2021-04-06 00:54:46

如果您将字符串作为函数的第一个参数传递,实际上会发生什么

设置超时( 'string', number)

是在运行时(经过number几毫秒评估的第一个参数的值基本上它等于

设置超时( eval('string'), number)

这是

一种替代语法,允许您包含一个字符串而不是一个函数,该函数在计时器到期时被编译和执行。不推荐使用此语法的原因与使用 eval() 存在安全风险的原因相同。

因此,您引用的样本不是好的样本,可能会在不同的上下文中给出,或者只是简单的错字。

如果您这样调用setTimeout(something, number),第一个参数不是字符串,而是指向名为something. 再次如果something是字符串 - 那么它将被评估。但是如果是函数,那么函数就会被执行。 jsbin 示例

    ##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.