面试问到了这个,之前只了解JavaScript的对象原型,作用域这些,这回认真理解一下单线程的执行逻辑。
对于JS来说,语言一大特点就是单线程,这是在原语言设计为dom操作脚本时因为复杂的同步问题设计成的。
为了避免dom操作冲突的复杂性,js单线程变成了一大特征不会改变。而单线程就意味着所有任务需要排队,前一个任务完成时再执行后面的。
ps:对象被分配在一个堆中,即用以表示一个大部分非结构化的内存区域,占用内存但不分担任务只做存储。
runtime
所有任务分成同步sync和异步任务async,所有同步任务直接在主线程上执行,形成执行栈。
每一个栈的桢执行完才会执行下一桢,执行时需要调用函数时,直接在该处使调用函数进栈,于栈顶立即执行。
而如setTimeout和ajax等,则相当于同步执行时,添加一个异步任务到异步任务队列中。
所有异步队列在同步,即执行栈,执行完后再按结果完成状态和先后进入顺序的开始执行。
异步队列子任务被吊起时,相当于执行同步任务一样,调入执行栈,执行可执行同步函数和调用函数,需要时再吊起异步任务到异步队列中。
主进程不断执行上述循环,可能这就是事件循环的意思吧。
特点
(function() {
console.log('this is the start');
setTimeout(function cb() {
console.log('this is a msg from call back');
});
// for (var i = 9999; i >= 0; i--) {
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');
})();
上面的例子就能看出执行顺序了,即使是0延迟的setTimeout,他还是会等到前面的所有同步任务执行完再执行,即使同步任务中可能有
执行时间超久的(如:for),他还是会等候同步栈执行完再执行异步队列相关,这就是Js的其中一个特点"执行至完成"。
"执行至完成"的意思就是,只有前面的同步任务,函数执行完,才会执行后面的,他不能被抢占。因此存在缺点,一个同步任务或者函数
如果长时间挂着的话,是不能执行其他交互函数的,整个页面或者交互就僵住了。。。所以同步不应该写太长久的逻辑或者可以剪开,或者分成异步写
或者写时间限制catch超时。
有了这个特点,就可以让js无堵塞,只进行快速的同步任务,不会因为交互的异步堵塞,可以在等待响应的同时执行其他项任务。