javascript为什么是单线程?
Javascript的主要用途是用户交互,主要是操作DOM。如果Javascript同时有两个线程,其中一个线程执行为当前DOM节点添加内容的操作,另一个线程执行删除当前节点的操作,这时这两个对节点的操作就会有很大的冲突,为了避免冲突,所以决定了它只能是单线程,否则会带来很复杂的操作同步问题。
javascript中为什么需要异步?
如果Javascript中不存在异步,只会自上而下执行,那么如果上一行代码执行很长时间,下面的代码就会被阻塞,造成页面假死状态,严重影响用户的体验;所以可以把耗时的操作放到异步中去执行。
- 什么时候需要异步处理
-
在可能发生等待的情况;
-
等待过程中不能像alert一样阻塞程序的时候;
-
因此,所有的“等待的情况”都需要异步
一句话总结就是需要等待但是又不能阻塞程序的时候需要使用异步
- 前端异步使用的场景
- 定时任务:setTimeout,setInverval;
- 网络请求:ajax请求,img图片的动态加载;
- 事件绑定或者叫DOM事件。
- 异步执行任务的好处
- 能够提高耗时的任务的执行效率,提高 JS 解析引擎的工作效率。
Javascript代码执行的顺序
- Javascript 的解析和执行一直是单线程的,但是**宿主环境(浏览器或node) **是多线程的;
- 异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务, 交给主线程执行;
- Javascript解析引擎,一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行。
图中的stack表示执行栈,web apis则是代表一些异步事件,而callback queue即事件队列。
- event Loop : 事件循环,当主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码…,如此反复,这样就形成了一个无限的循环,这也是javascript实现**“非阻塞”**的原因。
- 执行顺序
- JS主线程运行的时候,需要执行的方法存放在执行栈中,依次调用执行。
- 当遇到DOM事件、网络请求、计时器等需要耗时的操作时,他们的回调函数会被添加到(even queue)事件队列中。
- 主线程的代码执行完毕后,才会去执行事件队列中的代码。
- 以下简单的代码可以表现出来
let a = 10;
// 定时器的回调函数会被放在事件队列中
setTimeout(() => {
a = 20;
}, 0);
console.log(a); // --> 输出10
// 在执行栈中的代码执行完毕后,执行定时器的回调函数 --> a = 20;
如果需要20这个值,需要在回调函数中取值,否则得到的值是没有二次赋值的10。