搜索
首页web前端js教程深入理解JavaScript执行机制
深入理解JavaScript执行机制Aug 31, 2018 am 10:12 AM
javascript

本篇文章给大家带来的内容是关于深入理解JavaScript执行机制,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

首先我们大家都了解的是,JavaScript 是一门单线程语言,所以我们就可以得出:

JavaScript 是按照语句顺序执行的

首先看:

let a = '1'
console.log(a)

let b = '2'
console.log(b)

这个显然大家都知道结果,依次输出1,2

然而换一种:

setTimeout(function() {
    console.log(1)
})

new Promise(function(resolve) {
    console.log(2)
    for(var i = 0;i< 10;i++){
        i === 10 && resolve()
    }
}).then(function() {
    console.log(3)
})
console.log(4)

这个时候再看代码的顺序执行,输出1,2, 3, 4。好了放到浏览器运行一下,什么?输出居然是 2, 4, 3,1。说好的按顺序执行呢?下面就需要去了解一下 JavaScript 的执行机制问题了。

单线程

首先JavaScript 是一门单线程的语言,在最新的HTML5 推出的 Web-worker,但是 JavaScript 是一个单线程的语言这一个核心还是没有改变。所以,JavaScript 的多线程都是基于单线程模拟出来的。所以牢记    JavaScript 是单线程语言。

事件循环

任务分为两类:

  • 同步任务

  • 异步任务

当我们打开页面时,页面的渲染就是一大堆同步任务,而像加载图片和音频资源耗时的任务,就是异步任务。时间循环的主要内容就是:

  1. 当任务进入执行栈的时候,判断是同步任务还是异步任务,如果是同步任务,进入主线程进行执行,异步进入 Event Table 进行注册函数。

  2. 当指定的事件完成后,Event Table 将这个函数移入到事件队列

  3. 主线程中的任务执行完毕后,去任务队列读取对应的函数,进入主线程执行

  4. 上述的过程不断重复,也就构成了事件循环

其中js引擎存在一个监控进程,不断检查主线程执行栈是否为空,一旦为空,就会去时间队列那检查有没有等待被调用的函数。

例如:

setTimeout( function() {
    console.log(1)
}, 0)
console.log(2)
  • 首先 setTimeout进入Event Table

  • 执行console.log(2)

  • setTimeout执行的函数进入事件队列

  • 主线程从事件队列读取函数执行

这也就是为什么即使设置setTimeout(fn, 0)函数也不会立即执行的原因。不过即使主线程为空,0ms也是达不到的,根据HTML标准,最低是4ms。

setInterval

还有一个与setTimeout类似的函数,对于setInterval来说,是循环执行。对于执行顺序来说,setInterval会每隔指定的时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。

但是需要注意的一点是,对于setInterval(fn, ms)来说,他并不是每过ms执行一次 ,而是每过 ms 会有fn进入任务队列。也就是说如果setInterval 的回调函数的执行事件如果超过延迟ms,那么就看不出来事件间隔了。

Promise 和 process.nextTick(callback)

除了广义的同步任务和异步任务之外,还有对任务更精细的划分,分为:

  • macro-task(宏任务):包括整体代码script、setTimeout、setInterval

  • micro-task(微任务):Promise、process.nextTick

事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

用一段代码来说明:

setTimeout(function() {
    console.log('1');
})

new Promise(function(resolve) {
    console.log('2');
    resolve()
}).then(function() {
    console.log('3');
})

console.log('4');
  • 这段代码作为宏任务,开始第一次循环

  • 先遇到setTimeout,那么它的回调函数进入到宏任务事件队列中

  • 遇到Promise,Promise立即执行,输出2,then任务进入到微任务事件队列中

  • 下面遇到console,输出4

  • 第一个宏任务结束,看微任务事件队列,执行then,输出3

  • 第一轮循环结束,看宏任务队列中存在setTimeout的回调函数执行,输出1

  • 所有结果为:2,4,3,1

好了了解了基本的原理之后,我们来看一个更复杂的:

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. 首先整段代码作为一个宏任务进入主线程,首先遇到console.log()输出1

  2. 遇到第一个setTimeout()进入宏任务队列

  3. 遇到Process.nextTick()进入微任务队列

  4. 然后遇到Promise,立即执行,输出7,then被添加到微任务队列

  5. 遇到第二个setTimeout,进入宏任务队列

  6. 然后执行两个微任务

  7. 执行Process.nextTick()输出6

  8. 执行then,输出8

这样第一轮循环就彻底结束了,进行第二轮事件循环,也就是第一个setTimeout

  1. 首先遇到console.log(),输出2

  2. 遇到Process.nextTick(),进入微任务队列

  3. 遇到Promise立即执行输出4,then进入微任务队列

  4. 然后执行第一个微任务,输出3

  5. 执行then,输出5

这样第二轮事件循环就结束了,最后执行第二个setTimeout,第二个setTimeout和上面原理类似,也就不重复说明了。所以最终结果是:1,7,6,8,2,4,3,5,9,11,10,12

相关推荐:

js执行机制实例详解

JavaScript运行机制之Event Loop

以上是深入理解JavaScript执行机制的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具