setTimeout回调参数

jsn*_*man 15 javascript

让我们考虑一下这个JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.showName = function() {
    alert(this.name);
}


var mike = new Person("mike");
//mike.showName();  

window.name = "window"; 
Run Code Online (Sandbox Code Playgroud)

我不明白行为的区别

setTimeout(mike.showName(), 5000);
Run Code Online (Sandbox Code Playgroud)

setTimeout(function(){
    mike.showName();
}, 5000);
Run Code Online (Sandbox Code Playgroud)

为什么行为不同?这真让我困惑.谢谢.

Way*_*ett 55

你的问题真的没有任何关系setTimeout.您只需要了解函数调用和函数引用之间的区别.

考虑这四个任务:

var one = function() { mike.showName(); };
var two = mike.showName;
var three = mike.showName();
var four = (function() { mike.showName(); })();
Run Code Online (Sandbox Code Playgroud)

前两个将函数的引用分配给它们各自的变量.然而,最后两个调用函数(这是parens的用途)并将它们的返回值分配给左侧的变量.

这与setTimeout的关系如何:

setTimeout函数期望作为第一个参数一个参考到的函数,因此任一onetwo以上将是正确,但threefour不会.但是,重要的是要注意,严格来说,将函数的返回值传递给它并不是一个错误setTimeout,尽管你会经常看到这样说.

这非常好,例如:

function makeTimeoutFunc(param) {
    return function() {
        // does something with param
    }
}

setTimeout(makeTimeoutFunc(), 5000);
Run Code Online (Sandbox Code Playgroud)

它与如何 setTimeout接收函数作为其参数无关,但它确实如此.

  • @jsnewman - 传递`mike.showName()`说现在运行函数`showName`并传递它返回的任何内容作为要在5秒内执行的回调(这没什么).但是,传递`function(){mike.showName()}`为`setTimeout`提供了一个匿名函数,从现在开始运行五秒钟.经过五秒钟,执行外部包装器功能.它包含一行,即对"showName"的调用,该行在此时执行. (3认同)
  • 非常感谢人。你的回答很棒。但是我仍然有一个困惑。你能告诉我为什么 'mike.showName()' 会先执行而 'function(){ mike.showName()' 等待 5 秒吗?再次感谢。 (2认同)

JCO*_*611 21

如果接受的答案太长而无法阅读:

setTimeout(mike.showName(), 5000);
Run Code Online (Sandbox Code Playgroud)

这将在5,000毫秒后执行任何mike.showName() 返回.

setTimeout(function(){ mike.showName(); }, 5000);
Run Code Online (Sandbox Code Playgroud)

这将在调用5000毫秒后执行匿名函数mike.showName() ,即实际函数.

实现同样效果的另一种方法:

setTimeout(mike.showName.bind(mike), 5000);
Run Code Online (Sandbox Code Playgroud)


Thi*_*ter 9

这不是性能问题.你展示的方法之一根本不起作用(它立即调用函数,而不是在超时触发时).

setTimeout(mike.showName(), 5000);将执行该showName函数并将其返回值设置为超时回调,这将无效.

setTimeout(function(){ mike.showName(); }, 5000);创建一个匿名函数并将其设置为超时回调.当超时触发时,调用该函数并调用您的showName()函数.

Fyi,setTimeout('mike.showName();', 5000);也会工作.但是不要这样做 - 它和使用一样糟糕eval().除此之外,它使您的代码可读性降低,因为字符串中的代码不能以语法突出显示.


Mik*_*ark 5

setTimeout(mike.showName(), 5000);mike.showName()立即执行并将返回值传递给setTimeout()

setTimeout(function(){ mike.showName(); }, 5000);而是传递一个指向该函数的指针。这样setTimeout就可以执行函数,而不是它的返回值。