🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# setTimeout / setInterval ## setTimeout() > 方法用于在指定的毫秒数后调用函数或计算表达式 #### this的指向 在正常的使用中,this指向调用它的对象,但是在setTimeout中,this永远指向window全局。只要是setTimeOut就是全局。 ~~~ function Animal(login) { this.login = login; this.sayHi = function() { console.log(this.login); //undefined } } var dog = new Animal('John'); setTimeout(dog.sayHi, 1000); ~~~ 这里,sayHi的this就是指向window,只能输出undefined。 #### 参数为0时 ~~~ console.log('a'); setTimeout(function(){ console.log('b'); },0); console.log('c'); console.log('d'); ~~~ 这个例子就很简单了,因为setTimeOut参数为0时,就是立即执行。这个立即执行指的是脚本完全运行结束后的立即执行。所以时acdb这个顺序。 #### 事件循环中的setTimeOut 因为我们知道js的引擎时单线程的,在特定时间内只可以运行一个任务,并阻塞其他任务的进行,所以当异步方法比如这里的setTimeout(),或者ajax请求、DOM事件执行的时候,会交由浏览器内核的其他模块去管理。当异步的方法满足触发条件后,该模块就会将方法推入到一个任务队列中,当主线程代码执行完毕处于空闲状态的时候,就会去检查任务队列,将队列中第一个任务入栈执行,完毕后继续检查任务队列,如此循环。前提条件是主线程处于空闲状态,这就是事件循环的模型。 ~~~ setTimeout(function () { console.log("b"); },0) console.log("a"); ~~~ 这里输出的顺序为a-->b 同理,下面这个例子: ~~~ setTimeout(function(){ console.log(1111); },0) while (true) {}; ~~~ 永远都不会输出东西,因为while陷入了死循环,永远都不会运行console.log。 #### 两个题 1. 下面这个代码输出什么? ~~~ for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000); } ~~~ **对比(内部函数不一样)** ~~~ for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); } // 输出 5 5 5 5 5 ~~~ 给setTimeOut传入立即执行函数,就会立即执行,输出0到4. 2. 与promise配合 ~~~ setTimeout(function () { console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for (var i = 0; i < 10000; i++) { i == 9999 && resolve(); } console.log(3); }).then(function () { console.log(4); }); console.log(5); ~~~ 由于上面promise中的内容我们知道,promise的then在本段周期结束时执行,setTimeOut在下一段开始时执行,所以顺序就是23541.