这个是面试题中经常问的,再回答这个问题之前,我们需要知道以下几个知识点:
1.执行上下文context
2.函数调用栈
3.队列数据结构
4.promise,process.nexttick,setImmediate(其中promise大家都知道,后两个是node循环中必不可少的部分,node的高并发,异步I/O也是基于node事件循环)
不懂的兄弟们可以看看这个: github的mqyqingfeng/Blog,冴羽写得。
我们都知道javascript是单线程,只有唯一的事件循环。而javascript再执行过程中,除了函数调用栈来调节函数的执行顺序外,还有个任务队列task queue,任务队列可以是多个,其中又包括宏任务队列和微任务队列;
宏任务队列有:script(整体代码),setTimeout,setInterval,setImmediately,I/O,UI render
微任务队列有:promise,process.nexttick,Object.observe(已经不用了),Mutation.observe
-
MutationObserver的前身是MutationEvents(熟知的addEventListener就是一部分,已经不怎么用了),Mutation存在兼容问题,自行搜索,留下点实例用法
-
-
// Firefox和Chrome早期版本中带有前缀
-
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
-
// 选择目标节点
-
var target = document.querySelector('#some-id');
-
// 创建观察者对象
-
var observer = new MutationObserver(function(mutations) {
-
mutations.forEach(function(mutation) {
-
console.log(mutation.type);
-
});
-
});
-
// 配置观察选项:
-
var config = { attributes: true, childList: true, characterData: true }
-
// 传入目标节点和观察选项
-
observer.observe(target, config);
-
// 随后,你还可以停止观察
-
observer.disconnect();
如上文所讲,加了几个node的间谍,有兴趣的兄弟可以自己搜搜node的事件循环系统,真是回味无穷,这里就不详细介绍了。
事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的微任务。当所有可执行的微任务执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的宏任务,这样一直循环下去。其中每一个任务的执行,无论是微任务还是宏任务,都是借助函数调用栈来完成。