EventLoop概念
JavaScript 主线程从“任务队列”中读取异步 任务的回调函数,放到执行栈中依次执行。这 个过程是循环不断的,所以整个的这种运行机 制又称为 EventLoop(事件循环)。
任务执行顺序
- 同步任务由 JavaScript 主线程次序执行
- 异步任务委托给宿主环境执行
- 已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
- JavaScript 主线程的执行栈被清空后,会读取任务队列中的回调函数,按次序执行
- JavaScript 主线程不断重复上面的第 4 步
执行栈将异步任务委托给宿主环境,但宿主环境把异步任务执行之后会把回调函数放到任务队列中,然后排队依次执行,当js主线程把栈里面的任务清空之后 会主动把任务队列的任务取出来,再放到执行栈里面执行
闭包案例题
for(var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
-
for是同步任务,settimeout是异步执行;
-
每一次for循环的时候,settimeout都执行一次,里面的函数并没有执行,然后1000ms后将回调函数放到任务队列中,等待执行;
-
只有主线程上的全部执行完,才会执行任务队列里的任务,当主线执行完成后,for循环了3次,i是3,所以此时再去执行任务队列里的任务时,i全部是3了,也就是打印出三个3。
for(let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
setTimeout里面的function()属于一个新的域,通过 var 定义的变量是无法传入到这个函数执行域中的,通过使用 let 来声明块变量,这时候变量就能作用于这个块,所以 function就能使用 i 这个变量了;这个匿名函数的参数作用域 和 for参数的作用域 不一样,是利用了这一点来完成的。这个匿名函数的作用域有点类似类的属性,是可以被内层方法使用的。