执行顺序

一般执行顺序很显然按照创建顺序执行,对大对数开发者来说并不陌生。

像是这样:

foo();  // 报错
var foo = function () {console.log('foo1');}foo();  // foo1var foo = function () {console.log('foo2');}foo(); // foo2
复制代码

然而有的时候会是这样:

foo();  // foo2function foo() {console.log('foo1');}foo();  // foo2function foo() {console.log('foo2');}foo(); // foo2
复制代码

我们可以看到,作为函数调用的时候,会出现三个foo2。其实 JavaScript 引擎并非一行一行地分析和执行程序,在执行之前会对一些对结构进行分析执行。比如第一个例子中的变量提升,和第二个例子中的函数提升。 那么JS又是如何进行结构化的解析的呢?执行过程中又做了什么动作呢?

栈又是什么?

这张图分别展示了栈、堆和队列,其中栈就是我们所说的执行上下文栈;堆是用于存储复杂类型比如:对象,数组等等。队列就是异步队列,用于事件循环(event loop)的执行。 JS代码在引擎中是以代码片段的方式来分析执行的,而并非一行一行来分析执行。

简单的例子

//入栈过程
Stack.push("chris")Stack.push("james")Stack.push("kobe")//出栈过程Stack.pop() //["chirs","james"]Strack.pop() //["chirs"]Stack.pop() //[]
复制代码

可以看出,栈是执行过程是一个先入后出的过程。

可执行代码

而这些代码片段的可执行代码无非为三种:全局代码(Global code)函数代码(Function Code)eval代码(Eval code)。 这些可执行代码在执行的时候又会创建一个一个的执行上下文(Execution context)。例如,当执行到一个 函数的时候,JS引擎会做一些“准备工作”,而这个“准备工作”,我们称其为执行上下文。 那么随着我们的执行上下文数量的增加,JS引擎又如何去管理这些执行上下文呢?这时便有了执行上下文栈

执行上下文栈

问题来了,我们写的函数多了去了,如何管理创建的那么多执行上下文呢?

所以 JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)来管理执行上下文

为了模拟执行上下文栈的行为,让我们定义执行上下文栈是一个数组:

Stack= [];
复制代码

试想当 JavaScript 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执

行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,

Stack才会被清空,所以程序结束之前, Stack最底部永远有个 globalContext:

Stack = [globalContext// 一开始只有全局上下文
];
复制代码

一个简单的例子:

function fun3() {console.log('fun3')
}function fun2() {fun3();
}function fun1() {fun2();
}fun1();
复制代码

每当一个函数执行,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函

数的执行上下文从栈中弹出。


// fun1()
Stack .push(<fun1> functionContext);
//[globalContext,<fun1> functionContext]// fun1中有fun2,还要创建fun2的执行上下文
Stack .push(<fun2> functionCofuntext);
//[globalContext,<fun1> functionContext,<fun2> functionCofuntext],// fun2还调用了fun3
Stack .push(<fun3> functionContext);
//[globalContext,<fun1> functionContext,<fun2> functionCofuntext,<fun3> functionContext]      // fun3执行完毕
Stack .pop();
//[globalContext,<fun1> functionContext,<fun2> functionCofuntext]// fun2执行完毕
Stack .pop();
//[globalContext,<fun1> functionContext]// fun1执行完毕
Stack .pop();
//[globalContext]// javascript接着执行下面的代码,但是Stack 底层永远有个globalContext
复制代码

一个复杂的例子:

var scope = "global scope";
function checkscope(){var scope = "local scope";function f(){return scope;}return f();
}
checkscope();
复制代码
var scope = "global scope";
function checkscope(){var scope = "local scope";function f(){return scope;}return f;
}
checkscope()();
复制代码

两段代码执行的结果一样,但是两段代码究竟有哪些不同呢?

答案就是执行上下文栈的变化不一样。

先模拟第一段代码:

Stack.push(<checkscope> functionContext);
Stack.push(<f> functionContext);
Stack.pop();
Stack.pop();
复制代码

再模拟第二段代码:

Stack.push(<checkscope> functionContext);
Stack.pop();
Stack.push(<f> functionContext);
Stack.pop();
复制代码

我们可以发现二三部分出栈和入栈是不同的。

总结

  1. JS代码在引擎中是以一段一段的方式来分析执行的,而并非一行一行来分析执行
  2. 可执行代码分为三种:全局代码(Global code)函数代码(Function Code)eval代码(Eval code),其中全局代码函数代码比较常见,关于eval代码可参考JavaScript 为什么不推荐使用 eval?
  3. 每遇到函数执行的时候,就会创建一个执行上下文执行上下文会进入执行上下文栈
  4. 程序开始最先入栈和程序结束最后出栈的都是全局执行上下文

JavaScript基础专题系列

JavaScript基础专题系列目录地址:

JavaScript基础专题之原型与原型链(一)

JavaScript基础专题之执行上下文和执行栈(二)

新手写作,如果有错误或者不严谨的地方,请大伙给予指正。如果这篇文章对你有所帮助或者有所启发,还请给一个赞,鼓励一下作者,在此谢过。

转载于:https://juejin.im/post/5d0907cbe51d455a68490b7b

JavaScript基础专题之执行上下文和执行栈(二)相关推荐

  1. web前端知识集合——javascript基础篇之常量和变量(二)

    3. 变量和常量: 1.1 变量的声明: js三种方式声明变量,声明不赋值时,默认值为underfined. (1)var声明:var name='Ace',同时声明多个变量var a=1,b=2,c ...

  2. Javascript执行上下文和执行栈

    什么是执行上下文? 执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念,JavaScript中运行任何的代码都是在执行上下文. 什么是执行栈? 执行栈,在其他编程语言中也被叫做 ...

  3. 前端面试知识点总结JavaScript基础之原型和原型链(二)

    一.JavaScript基础 原型和原型链 1.理解原型设计模式以及JavaScript中的原型规则 设计模式 1.工厂模式:在函数内建立一个对象,给对象赋予属性及方法再将对象返回设计模式. func ...

  4. JavaScript基础之立即执行函数

    在JavaScript中有时候看到一些很神奇的函数比如下面截图: 这种函数只要浏览器加载的时候会自动运行,而需要调用,前面在闭包的时候也说过这种函数,一般将其称之为:立即执行函数. 立即函数的特征: ...

  5. 前端进击的巨人(一):执行上下文与执行栈,变量对象

    写在开篇 已经不敢自称前端小白,曾经吹过的牛逼总要一点点去实现. 正如前领导说的,自己喝酒吹过的牛皮,跪着都得含着泪去实现. 那么没有年终完美总结,来个新年莽撞开始可好. 进击巨人系列开篇,不忘初心, ...

  6. 前端进击的巨人(1):执行上下文与执行栈,变量对象

    (给前端大全加星标,提升前端技能) 作者:以乐之名 https://segmentfault.com/a/1190000017890535 写在开篇 已经不敢自称前端小白,曾经吹过的牛逼总要一点点去实 ...

  7. 2.JS执行上下文和变量对象

    文章目录 执行上下文栈 函数上下文 变量对象 执行过程 进入执行上下文 代码执行 两个例子 1 2   JS 是单线程语言,因此执行顺序是顺序执行,不过 JS 引擎在执行 JS 代码的时候并不是逐行执 ...

  8. web前端知识集合——javascript基础篇之javascript背景历史和运行环境(一)

    前言:温故而知新,可以为长也!万变不离其宗,无论是现在web前端技术衍生出多么优秀,好用的框架,插件,都离不开这门语言的基础知识.掌握各种优秀的框架,插件,只是"善用工具的人",深 ...

  9. Javascript中你必须理解的执行上下文和调用栈

    执行上下文在 JavaScript 是非常重要的基础知识,想要理解 JavaScript 的执行过程,执行上下文是你必须要掌握的知识.否则只能是知其然不知其所以然. 理解执行上下文有什么好处呢? 它可 ...

  10. 了解Javascript中的执行上下文和执行堆栈

    By Sukhjinder Arora | Aug 28, 2018 原文 如果你是或者你想要成为一名js开发者,那么你必须了解js程序内部的运作.理解执行上下文和执行堆栈对于理解js的其它概念(如提 ...

最新文章

  1. JS如何捆绑TypeScript声明文件
  2. String字符串类的获取功能
  3. alert,confirm和prompt
  4. 获取2个地址之间的距离(高德API)
  5. 多款主流编程语言,哪款开发软件最安全?
  6. html 存储登录状态,Vue中保存用户登录状态实例代码
  7. 禁用F12和鼠标右键,防止查看控制台代码
  8. Bootstrap 折叠插件Collapse 调用方式
  9. oracle数据库看开销,【Database】AIX系统下跟踪开销大的Oracle数据库进程
  10. 广二师的计算机专业好不,广东技术师范学院和广东第二师范学院哪一个更好?...
  11. 黄峥辞任董事长,超级投票权失效!拼多多已成为中国电商第一
  12. 比亚迪汽车发布品牌全新标识 取消了椭圆型边界
  13. [知识整理]Linux系统WIFI知识的一些整理
  14. git的SSH上传方式
  15. 线性布局LinearLayout(二)小练习
  16. PHP endif、endwhile、endfor、冒号、switch、foreach使用介绍、Heredoc 、Nowdoc
  17. 融合VOI与VDI、IDV、RDS,实现弹性的应用
  18. ts无损剪辑合并_软购团荐丨视频无损极速分割、合并、拼接。 处理视频比你想的更简单!...
  19. keras构建卷积神经网络
  20. 2021年第一季度中国电竞行业网络关注度分析报告

热门文章

  1. 算法:螺旋矩阵算出N行N列的数组Spiral Matrix II
  2. 广义注意力- saliency map 关注图、gaze、Att
  3. 使用折半查找法查找数组中的元素
  4. 数中唯一只出现一次的数字
  5. 努力在html中适配图片尝试失败
  6. 吴恩达《cs229-机器学习》:1、梯度下降法与一元线性回归
  7. n倍角公式的行列式形式与证明
  8. 导入es数据_有道精品课实时数据中台建设实践
  9. 服务器与交换机对接链路聚合mode=0模式传输带宽慢问题
  10. PathProber:基于暴力破解方法探测和发现HTTP路径名