• JavaScript系列之JS执行机制



    1、JS是单线程

    JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

    单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

    2、一个问题

    以下代码执行的结果是什么?

    console.log(1);
    setTimeout(function () {
    	console.log(3);
    }, 1000);
    console.log(2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果为:

    1
    2
    3
    
    • 1
    • 2
    • 3

    3、同步和异步

    为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Workers 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。

    3.1、同步

    前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

    3.2、异步

    你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

    3.3、同步和异步的本质区别

    这条流水线上各个流程的执行顺序不同。

    3.4、同步任务

    同步任务都在主线程上执行,形成一个执行栈。

    3.5、异步任务

    JS 的异步是通过回调函数实现的。
    一般而言,异步任务有以下三种类型:

    • 1、普通事件,如 click、resize 等
    • 2、资源加载,如 load、error 等
    • 3、定时器,包括 setInterval、setTimeout 等

    异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

    4、JS执行机制

    • 1、先执行执行栈中的同步任务。
    • 2、异步任务(回调函数)放入任务队列中。
    • 3、一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

    在这里插入图片描述

    5、示例

    console.log(1);
    document.onclick = function () {
    	console.log("click");
    };
    console.log(2);
    setTimeout(function () {
    	console.log(3);
    }, 3000);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果为

    1
    2
    3
    
    • 1
    • 2
    • 3

    6、事件循环

    由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。

    在这里插入图片描述

    7、宏任务和微任务

    7.1、宏任务

    计时器,ajax,读取文件

    7.2、微任务

    promise.then

    7.3、执行顺序

    1、同步程序
    2、process.nextTick
    3、微任务
    4、宏任务
    5、setImmediate

    7.4、示例

    //题目:
    setImmediate(() => {
    	console.log(1);
    });
    console.log(2);
    setTimeout(function () {
    	console.log(3);
    }, 0);
    setTimeout(function () {
    	console.log(4);
    }, 100);
    console.log(5);
    new Promise((resolve) => {
    	console.log(6); //promise.then的这个6是同步代码
    	resolve();
    }).then(() => {
    	console.log(7);
    });
    process.nextTick(() => {
    	console.log(8);
    });
    
    //执行顺序:2 5 6 8 7 3 1 4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    后记

    如果你感觉文章不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
    如果你觉得该文章有一点点用处,可以给作者点个赞;\\*^o^*//
    如果你想要和作者一起进步,可以微信扫描二维码,关注前端老L~~~///(^v^)\\\~~~
    谢谢各位读者们啦(^_^)∠※!!!

    在这里插入图片描述

  • 相关阅读:
    Rust6.2 An I/O Project: Building a Command Line Program (mini_grep)
    基于R语言、MATLAB、Python机器学习方法与案例分析
    前端面试题之【Vue】
    Mydb数据库问题
    Spring整合Mybatis,SqlSessionTemplate方式
    ubuntu20.04下源码编译colmap
    muduo源码学习base——Atomic(原子操作与原子整数)
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    【问题解决:配置】解决spring mvc项目 get请求 获取中文字符串参数 乱码
    JAVAEE初阶相关内容第十六弹--网络编程
  • 原文地址:https://blog.csdn.net/weixin_62277266/article/details/126071151