JavaScript深入之执行上下文栈
如果要问到 javascript 代码执行顺序的话,想必写过javascript的开发者都会有个直观的印象,那就是顺序执行,例如:
var foo = function(){
console.log('foo1')
}
foo() // foo1
var foo function(){
console.log('foo2')
}
foo() // foo2
然而去看这段代码:
function foo(){
console.log('foo1');
}
foo() // foo2
function foo(){
console.log('foo2')
}
foo() // foo2
打印的结果却是两个 foo2
刷过面试题的都知道这是因为javascript引擎并非一行一行的分析和执行程序,而是一段一段的分析执行。
当执行一段代码的时候,会进行一个“准备工作”,比如第一个例子中的变量提升,和第二个例子中的函数提升。
但是本文真正想让大家思考的是: 这个 “一段一段” 中的 “段” 究竟是怎么划分的呢?
到底 javascript 引擎遇到一段怎样的代码时才会做“准备工作”呢?
可执行代码
这就要说到 javascript 的可执行代码(executable code)的类型有哪些了?
其实很简单,就三种,全局代码,函数代码,eval代码。
举个例子,当执行到一个函数的时候,就会进行准备工作,这里的 “准备工作”, 让我们用个更专业一点的说法,就叫做 "执行上下文(execution context)"。
执行上下文栈
接下来问题来了,我们写的函数很多,如何管理创建的那么多执行上下文呢?
所以 javascript 引擎创建了执行上下文栈(Execution context stack, ECS) 来管理执行上下文。
为了模拟执行上下文栈的行为,让我们定义执行上下文栈是一个数组:
ECStask = [];
试想当javascript开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack才会被清空,所以 ECStack 最底部永远有个 globalContext:
ECStack = [
globalContext
]
现在javascript 遇到下面的这段代码了:
function fun3(){
console.log('fun3')
}
function fun2(){
fun3()
}
function fun1(){
fun2()
}
fun1();
当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。知道了这样的工作原理,让我们来看看如何处理上面这段代码:
// 伪代码
// fun1()
ECStack.push(<fun1> functionContext);
// fun1中竟然调用了fun2,还要创建fun2的执行上下文
ECStack.push(<fun2> functionContext);
// fun2中调用了 fun3
ECStack.push(<fun3> functionContext);
// fun3执行完毕
ECStack.pop();
// fun2执行完毕
ECStack.pop();
// fun1执行完毕
ECStack.pop();
// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext
参考文章:https://github.com/mqyqingfeng/Blog/issues/2
JavaScript深入之执行上下文栈的更多相关文章
- 【进阶1-2期】JavaScript深入之执行上下文栈和变量对象(转)
这是我在公众号(高级前端进阶)看到的文章,现在做笔记 https://mp.weixin.qq.com/s/hZIpnkKqdQgQnK1BcrH6Nw 阅读笔记 JS是单线程的语言,执行顺序肯定是顺 ...
- [JavaScript深入系列]JavaScript深入之执行上下文栈(转载)
顺序执行? 如果要问到 JavaScript 代码执行顺序的话,想必写过 JavaScript 的开发者都会有个直观的印象,那就是顺序执行,毕竟: var foo = function () { co ...
- 深入理解javascript原型和闭包(11)——执行上下文栈
继续上文的内容. 执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境.当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境.处于活动状态的执行 ...
- 前端知识体系:JavaScript基础-原型和原型链-理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题
理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题(原文文档) 1.什么是执行上下文: 简而言之,执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念,Java ...
- javascript系列之执行上下文
原文:javascript系列之执行上下文 写在前面:一 直想系统的总结一下学过的javascript知识,喜欢这门语言也热爱这门语言.未来想从事前端方面的工作,提前把自己的知识梳理一下.前面写了些 ...
- js基础梳理-究竟什么是执行上下文栈(执行栈),执行上下文(可执行代码)?
日常在群里讨论一些概念性的问题,比如变量提升,作用域和闭包相关问题的时候,经常会听一些大佬们给别人解释的时候说执行上下文,调用上下文巴拉巴拉,总有点似懂非懂,不明觉厉的感觉.今天,就对这两个概念梳理一 ...
- js执行上下文栈和变量对象
JavaScript执行上下文栈和变量对象 JS是单线程的语言,执行顺序肯定是顺序执行,但是JS 引擎并不是一行一行地分析和执行程序,而是一段一段地分析执行,会先进行编译阶段然后才是执行阶段. 例子一 ...
- 【学习笔记】深入理解js原型和闭包(11)——执行上下文栈
继续上文的内容. 执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境.当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境.处于活动状态的执行 ...
- JS高阶---执行上下文栈
大纲: 主体: 注意:*******函数调用时才会产生上下文栈,声明时不会产生********** 顺序: 概念图: 执行上下文栈的顺序---→后进先出 其他概念图: 当前执行的上下文总是在顶部 全局 ...
随机推荐
- Day 5-<补充> 类的的继承和查找顺序
类的继承于查找顺序: 在py2中,不继承object的类为经典类,经典类继承查找:深度优先. 在py3中,默认继承object,所以python3中都是新式类,新式类的继承查找:广度优先. 类的特殊属 ...
- javaScript中闭包的工作原理
一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...
- null值经过强转会怎样?
null还是null,类型不会改变的,也不会报错!
- 使用 idea 产生错误The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized
解决方法 spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache?serverTimezone=GMT%2B8
- 【转】Java基础——容器分类
Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类. 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 ...
- Linux基础学习笔记3-用户权限
本章内容 用户user 令牌token,identity Linux用户:Uername/UID 管理员:root,0 普通用户:1-65535 系统用户:1-499,1-999(Centos7) 对 ...
- re正则表达式-1
匹配/查找/替换/分割函数: import re re.match('aa','aabbcc') 返回对象中span为开始位置和结束位置 re.match('aa','bbaacc') #返回值为No ...
- vue之v-for使用说明
demo.html <!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/19 ...
- C#使用MemoryStream类读写内存
MemoryStream和BufferedStream都派生自基类Stream,因此它们有很多共同的属性和方法,但是每一个类都有自己独特的用法.这两个类都是实现对内存进行数据读写的功能,而不是对持久性 ...
- Mvc校验用户没有登录就跳转的实现
看字面意思很简单,就是判断用户是否登录了,如果没有登录就跳转到登陆页面. 没错,主要代码如下(这里就不写判断登录了,直接跳转) 首先在控制器中新建一个BaseController public cla ...