setTimeout 和 setInterval 潜在错误

setTimeout 的第一个参数是函数对象,一个常犯的错误是这样的 setTimeout(foo(), 1000), 这里回调函数是 foo 的返回值,而不是 foo 本身。 大部分情况下,这是一个潜在的错误,因为如果函数返回 undefined, setTimeout 也不会报错。

正确方式:

1
2
3
4
5
6
7
8
9
function Foo() {
    this.value = 42;
    this.method = function() {
        // this 指向全局对象
        console.log(this.value); // 输出:undefined
    };
    setTimeout(this.method, 500);
}
new Foo();




当回调函数的执行被阻塞时,setInterval 仍然会发布更多的回调指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来

最简单也是最容易控制的方案,是在回调函数内部使用 setTimeout 函数:

1
2
3
4
5
function foo(){
    // 阻塞执行 1 秒
    setTimeout(foo, 1000);
}
foo();




setTimeout 和 setInterval 也接受第一个参数为字符串的情况。这个特性绝对不要使用,因为它在内部使用了 eval。eval 函数会从全局作用域中执行。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。

小心 eval:

1
2
3
4
5
6
7
8
9
10
function foo() {
    // 将会被调用
}
function bar() {
    function foo() {
        // 不会被调用
    }
    setTimeout('foo()', 1000);
}
bar();