摘要:引擎的运行原理引擎也是程序,是属于浏览器的一部分,由浏览器厂商自行开发。为了提高运行速度,现代浏览器一般采用即时编译即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编译结果缓存这样整个程序的运行速度能得到显著提升。
相信大家在面试的过程中经常遇到查看执行顺序的问题,如setTimeout,promise,async await等等,各种组合,是不是感觉头都要晕掉了,其实这些问题最终还是考察大家对js的运行机制是否掌握牢固,对promise,async的原理是否掌握,万变不离其宗,这次就来彻底搞懂它。1 js引擎的运行原理
js引擎也是程序,是属于浏览器的一部分,由浏览器厂商自行开发。从头到尾负责整个JavaScript程序的编译及执行过程
浏览器在渲染的过程中,首先按顺序加载由首先,进入全局环境,就会先进行预处理,然创建全局上下文执行环境(Global ExecutionContext),会对var声明的变量和函数声明进行预处理,window对象就是全局执行上下文的变量对象,所有的变量和函数都是window对象的属性方法。所以函数声明提前和变量声明提升是在创建变量对象中进行的,且函数声明优先级高于变量声明。然后推入stack栈中。预处完成之后,开始执行js
当执行bar()时,就会进入bar函数运行环境,就会先进行预处理,创建bar函数执行上下文(bar Execution Context),推入stack栈中,预处理完后,开始执行foo()
在bar函数内部调用foo函数,则再进入foo函数运行环境,创建foo函数执行上下文(foo Execution Context),推入stack栈中
此刻栈底是全局执行上下文(Global Execution Context),栈顶是foo函数执行上下文(foo Execution Context),如上图,由于foo函数内部没有再调用其他函数,那么则开始出栈
foo函数执行完毕后,栈顶foo函数执行上下文(foo Execution Context)首先出栈
bar函数执行完毕,bar函数执行上下文(bar Execution Context)出栈
Global Execution Context则在浏览器或者该标签页关闭时出栈。
1.2.3 执行上下文分析一段简单的代码,帮助我们理解创建执行上下文的过程,如下:
function fun(a, b) { var num = 1; function test() { console.log(num) } } fun(2, 3)这里我们在全局环境调用fun函数,创建fun执行上下文,这里为了方便大家理解,暂时不讲解作用域链以及this指向,如下:
funEC = { //变量对象 VO: { //arguments对象 arguments: { a: undefined, b: undefined, length: 2 }, //test函数 test:, //num变量 num: undefined }, //作用域链 scopeChain:[], //this指向 this: window } funEC表示fun函数的执行上下文(fun Execution Context简写为funEC)
funE的变量对象中arguments属性,上面的写法仅为了方便大家理解,但是在浏览器中展示是以类数组的方式展示的
表示test函数在堆内存地址的引用 注:创建变量对象发生在预编译阶段,但尚未进入执行阶段,该变量对象都是不能访问的,因为此时的变量对象中的变量属性尚未赋值,值仍为undefined,只有进入执行阶段,变量对象中的变量属性进行赋值后,变量对象(Variable
Object)转为活动对象(Active Object)后,才能进行访问,这个过程就是VO –> AO过程。建立作用域链
作用域链由当前执行环境的变量对象(未进入执行阶段前)与上层环境的一系列活动对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。理清作用域链可以帮助我们理解js很多问题包括闭包问题等,下面我们结合一个简单的例子来理解作用域链,如下:
var num = 30; function test() { var a = 10; function innerTest() { var b = 20; return a + b } innerTest() } test()在上面的例子中,当执行到调用innerTest函数,进入innerTest函数环境。全局执行上下文和test函数执行上下文已进入执行阶段,innerTest函数执行上下文在预编译阶段创建变量对象,所以他们的活动对象和变量对象分别是AO(global),AO(test)和VO(innerTest),而innerTest的作用域链由当前执行环境的变量对象(未进入执行阶段前)与上层环境的一系列活动对象组成,如下:
innerTestEC = { //变量对象 VO: {b: undefined}, //作用域链 scopeChain: [VO(innerTest), AO(test), AO(global)], //this指向 this: window }在这里我们顺便思考一下,什么是闭包?
我们先看下面一个简单例子,如下:function foo() { var num = 20; function bar() { var result = num + 20; return result } bar() } foo()我这里直接以浏览器解析,以浏览器理解的闭包为准来分析闭包,如下图:
如上图所示,chrome浏览器理解闭包是foo,那么按浏览器的标准是如何定义闭包的,我总结为三点:
在函数内部定义新函数
新函数访问外层函数的局部变量,即访问外层函数环境的活动对象属性
新函数执行,创建新的函数执行上下文,外层函数即为闭包
确定this指向
在全局环境下,全局执行上下文中变量对象的this属性指向为window;函数环境下的this指向却较为灵活,需根据执行环境和执行方法确定
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/54701.html
摘要:的执行机制就是一个主线程一个任务队列。同步任务就是放在主线程上执行的任务,异步任务就是放在任务队列的任务。和上述运行的机制主要说明的是,而的出现及普及,又有了新的概念,,它的出现,进一步,中分为两种任务类型和,在中,称为,可称为。 上一篇文章主要整理了一下js引擎是如何工作的,这篇文章主要整理js的事件循环Event loop,以及异步编程的原理 事件循环Event loop 之前文章...
摘要:的执行机制就是一个主线程一个任务队列。同步任务就是放在主线程上执行的任务,异步任务就是放在任务队列的任务。和上述运行的机制主要说明的是,而的出现及普及,又有了新的概念,,它的出现,进一步,中分为两种任务类型和,在中,称为,可称为。 上一篇文章主要整理了一下js引擎是如何工作的,这篇文章主要整理js的事件循环Event loop,以及异步编程的原理 事件循环Event loop 之前文章...
摘要:引擎的运行原理引擎也是程序,是属于浏览器的一部分,由浏览器厂商自行开发。为了提高运行速度,现代浏览器一般采用即时编译即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编译结果缓存这样整个程序的运行速度能得到显著提升。 相信大家在面试的过程中经常遇到查看执行顺序的问题,如setTimeout,promise,async await等等,各种组合,是不是感觉头都要晕掉了,其实这些问题最...
摘要:当主线程开始执行异步任务,实际就是执行对应的回调函数。异步任务必须指定回调函数。所以注意的是,只是将事件插入了任务队列,必须等到当前代码执行栈执行完,主线程才会去执行它指定的回调函数。 最近本人对于js的运行机制,特别是异步,还有回调函数感觉很乱,于是参考了很多有用的博客(博客原文地址会在文末给出),整理如下: js单线程 我们都知道,Javascript语言的执行环境是单线程(si...
摘要:回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。同步方式请求异步同步请求当请求开始发送时,浏览器事件线程通知主线程,让线程发送数据请求,主线程收到 一直以来都知道JavaScript是一门单线程语言,在笔试过程中不断的遇到一些输出结果的问题,考量的是对异步编程掌握情况。一般被问到异步的时候脑子里第一反应就是Ajax,setTimse...
阅读 3675·2021-10-13 09:39
阅读 3742·2021-09-24 09:48
阅读 1138·2021-09-01 10:30
阅读 2499·2019-08-30 15:55
阅读 1744·2019-08-29 16:39
阅读 2224·2019-08-26 13:55
阅读 3026·2019-08-26 12:23
阅读 1603·2019-08-26 11:59