JavaScript是单线程的,它的执行顺序是从上到下一行一行执行的,即只有当上一行的代码执行完后才会执行下一行代码,这样的设定也是为了保证我们在实现某些功能时的代码逻辑的顺序性。在JS中有些代码是异步执行的,所谓异步,就是不会阻塞代码的运行,而会另外开启一个空间去执行这段异步代码,其余同步的代码就仍正常执行,若异步代码中有其它的代码,则会在之后的某个时刻将异步代码中其它代码执行。

为什么 JavaScript 是单线程 ?

JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript 不能有多个线程呢 ?这样能提高效率啊。

JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

所以,为了避免复杂性,从一诞生,JavaScript 就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

为了利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变 JavaScript 单线程的本质。

JavaScript是单线程,怎样执行异步的代码 ?

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

js 引擎执行异步代码而不用等待,是因有为有 消息队列和事件循环。

  • 消息队列:消息队列是一个先进先出的队列,它里面存放着各种消息。
  • 事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。

实际上,主线程只会做一件事情,就是从消息队列里面取消息、执行消息,再取消息、再执行。当消息队列为空时,就会等待直到消息队列变成非空。而且主线程只有在将当前的消息执行完成后,才会去取下一个消息。这种机制就叫做事件循环机制,取一个消息并执行的过程叫做一次循环。

js任务分为两类:

  • 同步任务
  • 异步任务