js实现事件循环的方式
1.执行栈和事件队列:当javascript代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针;当我们调用一个方法的时候,js会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中存在着这个方法的私有作用域,上层作用域的指向,方法的参数,这个作用域中定义的变量以及这个作用域的this对象。 而当一系列方法被依次调用的时候,因为js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方。这个地方被称为执行栈。
线程:是一个程序内部的顺序控制流,可以看做轻量级进程,同一类线程共享代码和数据空间,有独立的运行栈和程序计数器(pc)(用来存放当前想要执行指令的地址,它与主存的MAR之间有一条直接通路,且具有自加1的功能,即可形成下一条指令的地址)
当程序启动时, 一个进程被创建,同时也运行一个线程, 即为主线程,js的运行机制为单线程
- 主线程读取js代码, 形成相应的堆和执行栈, 执行同步任务
- 当主线程遇到异步任务,,指定给异步进程处理, 同时继续执行同步任务
- 当异步进程处理完毕后, 将相应的异步任务推入到任务队列首部
- 主线程任务处理完毕后,,查询任务队列,则取出一个任务队列推入到主线程的执行栈
- 重复执行第2、3、4步,这就称为事件循环
其中的异步进程有:
- 类似onclick等,由浏览器内核的DOM binding模块处理,事件触发时,回调函数添加到任务队列中;
- setTimeout等,由浏览器内核的Timer模块处理,时间到达时,回调函数添加到任务队列中;
- Ajax,由浏览器内核的Network模块处理,网络请求返回后,添加到任务队列中。