自查问题
- 控制台会打印1吗,为什么
function loop() {
Promise.resolve().then(loop);}setTimeout(() => {console.log(1)}, 0);loop();
- 页面有个link,当hover时样式会从灰变绿,现在在控制台加下面的脚本,会怎么样,hover还会变绿吗
while (true);
- 控制台的打印
Promise.resolve(1).then((x) => { console.log(x); return x + 1 }).then((x) => {console.log(x);})
Promise.resolve(10).then((x) => { console.log(x); return x * 10}).then((x) => {console.log(x);})
事件循环图
我们最终需要理解的目标就是上图。
事件循环
while (true) {
if (execQueue.isNotEmpty()) {
execQueue.pop().exec();
}
}
任务队列有任务就执行。
任务有如下几种:
-
任务队列: 所有事件,延时任务
-
微任务: promise回调,mutationObserver
微任务
特点是:只要当前callstack为空,就会清空微任务队列,因此有可能会阻塞渲染,永远不执行renderQueue的任务
Render Queue
渲染队列的任务就是完成一次渲染,渲染频率取决于硬件,可以简单理解每隔16ms,会向render queue放一个渲染任务。
回流
回流是计算元素布局信息的步骤。当页面resize或者读取某些属性时都会触发,这叫做强制回流。需要注意:强制回流会暂停执行js代码。
比如下面的代码会触发两次回流操作
div1.style.height = "200px";
var height1 = div1.clientHeight; // <-- layout 1
div2.style.margin = "300px";
var height2 = div2.clientHeight; // <-- layout 2
而将读写分离开,只会触发一次操作
div1.style.height = "200px";
div2.style.margin = "300px";
var height1 = div1.clientHeight; // <-- layout 1
var height2 = div2.clientHeight;