setTimeout 接受两种参数︰
var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);
var timeoutID = scope.setTimeout(code[, delay]);
你的正常写法和错误写法,分别对应第一种、第二种呼叫方法,这里就不说明。
来看你的错误写法︰
: setTimeout(console.log(2),1000);
console.log(2) 会呼叫 console.log 这个函式,并传入参数 2。console.log 这个函式
没有回传值,得到的结果是 undefined。也就是说,你的错误写法相当于
1. 执行 console.log(2) 之后
2. 使用 undefined 作为第一个参数传入 setTimeout︰
setTimeout(undefined,1000);
那为什么没有错误?
因为当 setTimeout 接受到的第一个参数不是函式的时候,会尝试将该数值转成字串。也
就是说,它相当于︰
setTimeout((undefined).toString(),1000);
setTimeout('undefined',1000);
你相当于在一秒后执行了一段内容为“undefined”的程式码。
基于这个特性,我们其至可以把要执行的程式码设置成 toString 的回传内容︰
const foo = {};
foo.toString = () => "console.log('hello')";
setTimeout(foo, 1000);
// 在一秒后印出 hello
参考︰
* MDN 上的 setTimeout 文件︰
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
(缩︰https://is.gd/YOpwh2)
* setTimeout 的详细实作参考︰
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
(缩︰https://is.gd/4DlMT2)