浏览器端,复杂的UI环境会限制多线程语言的开发。
例如,一个线程在操做一个DOM元素时,另外一个线程须要去删除DOM元素,
这个之间就须要进行状态的同步,况且前端可能不止操做这么一个DOM元素。
因此,为了不在开发过程当中,去进行复杂的同步,选用单线程语言进行开发是最好的解决方案
栈就是和列表相似的一种数据结构,它能够用来解决计算机世界里不少的问题。栈是一种高效的数据结构,由于数据只能在栈顶添加或删除,因此这样的操做很快,并且容易实现。
栈的使用遍及程序语言的方方面面,从表达式求值处处理函数调用; 函数调用造成了一个栈帧
具备一种后入先出(LIFO,last-in-first-out)的数据结构
因为栈具备后入先出的特色,全部任何不在栈顶的元素都没法访问,为了拿到栈底的元素,必选先拿掉上面的元素
可在线演示这段代码的执行流程javascript
function fun1(){
return 'hello hip-hop';
}
function fun2(){
return fun1();
}
function fun3(){
console.log(fun2());
}
fun3(); //'hello hip-hop'
复制代码
当咱们在程序中建立一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(由于对象的建立成本开销较大),这个运行时数据区就是堆内存。
堆内存中的对象不会随方法的结束而销毁,即便方法结束后,这个对象还可能被另外一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,
系统的垃圾回收机制才会在核实的时候回收它对象被分配在一个堆中,即用以表示一个大部分非结构化的内存区域
排队在第一个的人先办理业务,其它人只能排着,直到轮到他们为止只能在末尾插入元素,在队首删除元素。
队列用于存储按顺序排列的数据 先进先出列被用在不少地方。好比提交操做系统执行一系列进程。打印任务池等。一些仿真系统用来模拟银行或杂货店里排队的顾客
这幅图片中,咱们能够看到完整的执行流程,其中涉及到的异步事件有DOM事件、ajax请求和setTimeout。因此,总体的执行流程是这样子的:前端
这样,咱们就已经初步了解了同步和异步之间的实现,以及浏览器中的事件循环机制。java
所谓任务是WebAPIs返回的一个个通知,让JS主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。
主线程拥有多个任务队列,不一样的任务队列用来排列来自不一样任务源的任务。
任务源是什么?像setTimeout/Promise/DOM事件等都是任务源,来自同类任务源的任务咱们称它们是同源的,好比setTimeout与setInterval就是同源的。
在ES6标准中任务队列又分为宏观任务队列和微观任务队列ajax
ES6标准中任务队列存在两种类型,一种就是上边提到的一些队列,
宏观任务队列(macrotask queue):setTimeout、网络请求Ajax、用户IO等,
微观任务队列(microtask queue),Promise就属于微观任务队列
在执行栈执行的过程当中会把属于微观任务队列的任务分配到相应的微观任务队列中去。而在调用栈执行空以后,主线程读取任务队列时,会先读取全部微观任务队列,而后读取一个宏观任务队列,再读取全部的微观任务队列
复制代码
setTimeout(function(){console.log(4)},0);
new Promise(function(resolve){
console.log(1)
for( var i=0 ; i<10000 ; i++ ){
i==9999 && resolve()
}
console.log(2)
}).then(function(){
console.log(5)
});
console.log(3);
复制代码
因此最后的输出顺序是1,2,3,5,4,而不是1,2,3,4,5。若是不清楚微观任务队列的执行机制,很容易将两个异步任务归为一类,将执行顺序判断错误浏览器
零延迟并非意味着回调会当即执行。 在零延迟调用 setTimeout 时,其并非过了给定的时间间隔后就立刻执行回调函数。
其等待的时间基于队列里正在等待的消息数量。 在下面的例子中,"this is just a message" 将会在回调
(callback) 得到处理以前输出到控制台, 这是由于延迟是要求运行时 (runtime) 处理请求所需的最小时间,但不是有所保证的时间
(function () {
console.log('this is the start');
setTimeout(function cb() {
console.log('this is a msg from call back');
});
console.log('this is just a message');
setTimeout(function cb1() {
console.log('this is a msg from call back1');
}, 0);
console.log('this is the end');
})();
// "this is the start"
// "this is just a message"
// "this is the end"
// "this is a msg from call back"
// "this is a msg from call back1"复制代码