事件循环

事件循环

  • JS运行的环境称之为宿主环境。
  • 执行栈:call stack,一个数据结构,用于存放各种函数的执行环境,每一个函数执行之前,创建执行环境,然后加入到执行栈,函数调用之后,销毁执行环境。
  • JS引擎永远执行的是执行栈的最顶部。
  • 例如:执行以下代码
function a(){
console.log("a")
b();
}

function b(){
console.log("b")
c();
}
function c(){
console.log("c")
}
console.log("global");
a();

函数执行 形成全局上下文,console.log(“global”);函数执行形成上下文执行后销毁,a()执行形成函数a的上下文,console.log(“a”);执行输出a后销毁,b();执行形成函数b的上下文,console.log(“b”)执行 后销毁,c();执行形成函数c的上下文,console.log(“c”);执行后销毁,函数c的执行上下文出栈,函数b的执行上下文出栈,函数a的执行上下文出栈,最终全局上下文出栈

 // 1  1  2  3  5  8  13

        //求斐波拉契数列第n位的值
        function getFeibo(n) {
            if (n === 1 || n === 2) {
                return 1;
            }
            return getFeibo(n - 1) + getFeibo(n - 2);
        }

        console.log(getFeibo(4));
        // 避免出现无限递归 容易出现内存不够

函数执行 形成全局上下文, console.log(getFeibo(4));执行

异步函数:某些函数不会立即执行,需要等到某个时机到达后才会执行,这样的函数称之为异步函数。比如事件处理函数。异步函数的执行时机,会被宿主环境控制。

浏览器宿主环境中包含5个线程:

  1. JS引擎:负责执行执行栈的最顶部代码
  2. GUI线程:负责渲染页面
  3. 事件监听线程:负责监听各种事件
  4. 计时线程:负责计时
  5. 网络线程:负责网络通信

当上面的线程发生了某些事请,如果该线程发现,这件事情有处理程序,它会将该处理程序加入一个叫做事件队列的内存。当JS引擎发现,执行栈中已经没有了任何内容后,会将事件队列中的第一个函数加入到执行栈中执行。

JS引擎对事件队列的取出执行方式,以及与宿主环境的配合,称之为事件循环。

 <div>
        <button id="btn">点击</button>
    </div>

    <script>
        document.getElementById("btn").onclick = function A() {
            console.log("按钮被点击了");
        }
        // 当onclick 赋值一个函数时 浏览器宿主中有事件监听线程 监听按钮点击 运行函数a
        // 当JS引擎发现,执行栈中已经没有了任何内容后,会将事件队列中的第一个函数加入到执行栈中执行。
        // 就会看事件队列里是否有东西,如果没有等待,当点击的一瞬间 会把函数A放到事件队列中,然后把函数a加入
        // 到执行栈中 执行函数a log执行后销毁,
   

事件队列在不同的宿主环境中有所差异,大部分宿主环境会将事件队列进行细分。在浏览器中,事件队列分为两种:

  • 宏任务(队列):macroTask,计时器结束的回调、事件回调、http回调等等绝大部分异步函数进入宏队列
  • 微任务(队列):MutationObserver,Promise产生的回调进入微队列

MutationObserver用于监听某个DOM对象的变化

当执行栈清空时,JS引擎首先会将微任务中的所有任务依次执行结束,如果没有微任务,则执行宏任务。


let count = 1;
        const ul = document.getElementById("container");
        document.getElementById("btn").onclick = function A() {
            setTimeout(function C() {
                console.log("添加了一个li")
            }, 0);
            var li = document.createElement("li")
            li.innerText = count++;
            ul.appendChild(li);
        }

        //监听ul
        const observer = new MutationObserver(function B() {
            //当监听的dom元素发生变化时运行的回调函数
            console.log("ul元素发生了变化")
        })
        //监听ul
        observer.observe(ul, {
            attributes: true, //监听属性的变化
            childList: true, //监听子元素的变化
            subtree: true //监听子树的变化
        })
        //取消监听
        // observer.disconnect();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值