setTimeout的异步以及js是单线程的面试题?

var t = true; window.setTimeout(function (){ t = false; },1000); while (t){…
关注者
78
被浏览
24,079
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

此处我就不涉及什么http请求线程、gui渲染线程


单线程是JavaScript的一大特性。

JavaScript不像其他语言比如Java一样多线程,就不必去考虑线程同步的问题。

JavaScript是浏览器用来与用户进行交互、进行DOM操作的,这也使得了它必须是单线程这一特性。比如你去修改一个元素的DOM,同时又去删除这个元素,那么浏览器应该听谁的?

在JavaScript中任务有两种,一种是同步任务,一种是异步任务。

同步任务:各个任务按照文档定义的顺序一一推入"执行栈"中,当前一个任务执行完毕,才会开始执行下一个任务。

异步任务:各个任务推入"任务队列"中,只有在当前的所有同步任务执行完毕,才会将队列中的任务"出队"执行。(注:这里的异步任务并不一定是按照文档定义的顺序推入队列中)

//只有用户触发点击事件才会被推入队列中(如果点击时间小于定时器指定的时间,则先于定时器推入,否则反之)
document.querySelector("#box").onclick = function(){
  console.log("click");
};
//第一个推入队列中
setTimeout(function(){
  console.log("1");
},0);
//第三个推入队列中
setTimeout(function(){
 console.log("2");
},1000);
//第二个推入队列中
setTimeout(function(){
  console.log("3");
},0);

当然了,这时候你会疑惑"任务队列是什么?异步任务通常包括哪些?"

任务队列(event loop):你可理解为用于存放事件的队列,当执行一个异步任务时,就相当于执行任务的回调函数。

通常io(ajax获取服务器数据)、用户/浏览器自执行事件(onclick、onload、onkeyup等等)以及定时器(setTimeout、setInterval)都可以算作异步操作

我所知道的有这些,如果有其它的事件是异步的,欢迎大大补充。


先来看一段代码来理解一下

console.log("1");

setTimeout(function(){
	console.log("2");
},1000);

console.log("3");

setTimeout(function(){
	console.log("4");
},0);

输出结果: 1->3->4->2.

分析

1. 两个console.log()都是同步,按照文档的顺序将它们推入"执行栈"中。

2. 执行栈中的同步任务执行完毕。

3. 将两个异步任务(定时器)按照第二个参数(延迟执行的时间)顺序推入"任务队列"中。

4. 一一执行异步任务。


那么在来看你这段代码。

//同步code1
var t = true;

//异步code2
window.setTimeout(function (){
    t = false;
},1000);

//同步code2
while (t){}

//同步code3
alert('end');

分析

1. 先执行同步code1->同步code2。

2. 此时while(true){},进入死循环,以后的代码都不会执行。