理解JS的三座大山

如图所示,JS的三座大山:

  • 同步、异步
  • 作用域、闭包
  • 原型、原型链

1. 同步、异步

JavaScript执行机制,重点有两点:

  1. JavaScript是一门单线程语言
  2. Event Loop(事件循环)是JavaScript的执行机制

JS为什么是单线程

最初设计JS是用来在浏览器验证表单操控DOM元素的是一门脚本语言,如果js是多线程的,那么两个线程同时对一个DOM元素进行了相互冲突的操作,那么浏览器的解析器是无法执行的。

js为什么需要异步

如果js中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。

对于用户而言,阻塞就以为着“卡死”,这样就导致了很差的用户体验。比如在进行ajax请求的时候如果没有返回数据后面的代码就没办法执行

JS的事件循环(eventloop)是怎么运作的

  1. 首先判断JS是同步还是异步,同步就进入主线程运行,异步就进入event table.

  2. 异步任务在event table中注册事件,当满足触发条件后,(触发条件可能是延时也可能是ajax回调),被推入event queue

  3. 同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程中。

    如图所示:

    那怎么知道主线程执行栈为空呢?js引擎存在 monitoring process 进程,会持续不断的检查 主线程 执行栈 是否为空,一旦为空,就会去 event queue 那里检查是否有等待被调用的函数

    宏任务包含整个script代码块,setTimeout, setIntval

    微任务Promise , process.nextTick

    在划分宏任务、微任务的时候并没有提到async/ await的本质就是Promise

    setTimeout(function() {
     
        console.log('4')
    })
    
    new Promise(function(resolve) {
     
        console.log('1') // 同步任务
        resolve()
    }).then(function() {
     
        console.log('3')
    })
    console.log('2')
    执行结果: 1-2-3-4
    1. 这段代码作为宏任务,进入主线程。
    2. 先遇到setTimeout,那么将其回调函数注册后分发到宏任务event queue.
    3. 接下来遇到Promise, new Promise立即执行,then函数分发到微任务event queue
    4. 遇到console.log(), 立即执行
    5. 整体代码script作为第一个宏任务执行结束, 查看当前有没有可执行的微任务,执行then的回调。(第一轮事件循环结束了,我们开始第二轮循环)
    6. 从宏任务的event queue开始,我们发现了宏任务event queue中setTimeout对应的回调函数,立即执行。
    console.log('1')
    setTimeout(function() {
     
        console.log('2')
        process.nextTick(function() {
     
            console.log('3')
        })
        new Promise(function(resolve) {
     
            console.log('4')
            resolve()
        }).then(function() {
     
            console.log('5')
        })
    })
    
    process.nextTick(function() {
     
        console.log('6')
    })
    
    new Promise(function(resolve) {
     
        console.log('7')
        resolve()
    }).then(function() {
     
        console.log('8')
    })
    
    setTimeout(function() {
     
        console.log('9')
        process.nextTick(function() {
     
            console.log('10')
        })
        new Promise(function(resolve) {
     
            console.log('11')
            resolve()
        }).then(function() {
     
            console.log('12')
        })
    })
    1.整体script作为第一个宏任务进入主线程,遇到console.log(1)输出1
    
    遇到setTimeout, 其回调函数被分发到宏任务event queue中。我们暂且记为setTimeout1
    3.遇到process.nextTick(),其回调函数被分发到微任务event queue中,我们记为process1
    4.遇到Promise, new Promise直接执行,输出7.then被分发到微任务event queue中,我们记为then1
    又遇到setTimeout,其回调函数被分发到宏任务event queue中,我们记为setTimeout2.
    现在开始执行微任务, 我们发现了process1和then1两个微
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值