JavaScript是单线程非阻塞的脚本语言,这意味着JavaScript只有一条主线程来处理所有任务,当主线程遇到同步任务时会直接处理此任务,当遇到异步任务时,会先将此任务“挂”起来,等到条件成熟时再去执行该任务的回调函数。
JavaScript存在一个类似while(true)
一样的循环机制,一直运行着,它的作用就是处理同步任务和异步任务。
当我们我们执行一个方法时,JavaScript会生成与这个方法对应的执行环境,我们称它为执行上下文
,这个执行上下文保存着这个方法的私有作用域、上层作用域的指向、方法的参数、this对象和局部变量。而执行上下文会被添加到一个栈里,这个栈称为执行栈,遵循后进先出的规则。
执行上下文有三种:
eval
函数容易导致恶意攻击,不推荐使用)我们以主线程执行函数调用语句为例,当主线程执行到一条函数调用语句时,并不会立马执行该函数,而是会先生成该函数的执行上下文,将函数执行上下文压入栈中,然后再执行函数内的代码,然后返回结果。当函数内的代码未执行完毕时,此函数的执行上下文一直在栈中,而函数执行完毕时,该函数执行上下文会出栈销毁,这种出栈入栈的过程反复进行,直到执行栈中的代码全部执行完毕。
由此可见,执行栈是JavaScript管理执行上下文的。在整个函数执行过程中,确保函数执行上下文在函数执行过程中一直存在,进而确保函数执行时函数内的this对象、局部变量、参数等可被访问。
注意:并非所有栈顶的执行上下文出栈都会被销毁,如果它是被挂起并保留以供可访问的生成器对象,则不能销毁它。
当主线程遇到异步任务时,会将其加入到队列(先进先出)中,而根据异步任务的不同,所进入的队列又有所不同,宏任务进入任务队列,微任务会进入到微任务队列。
异步任务分为
属于微任务的事件包括但不限于以下几种: