Javascript执行上下文和执行栈
什么是执行上下文?
执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念,JavaScript中运行任何的代码都是在执行上下文。
什么是执行栈?
执行栈,在其他编程语言中也被叫做调用栈,具有LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文。当JavaScript引擎首次读取脚本时,它会创建一个全局执行上下文并将其推入当前的执行栈。每当发生一个函数调用,引擎都会为该函数创建一个新的执行上下文,并将其推到当前执行栈的顶端。引擎会运行执行上下文在执行栈顶端的函数,当此函数运行完成后,其对应的执行上下文将会从执行栈中弹出,上下文控制权将移到当前执行栈的下一个执行上下文。所以程序结束以前,执行栈最底部永远有一个globalContext。
执行上下文的类型
执行上下文总共有三种类型:
一、全局执行上下文:这是默认的,基础的执行上下文。不在任何函数中的代码都位于全局执行上下文中,做了两件事:1.创建一个全局对象,在浏览器中这个全局对象就是window对象。2.将this指针指向这个全局对象。一个程序中只能存在一个全局执行上下文。
二、函数执行上下文:每次调用函数时,都会为该函数创建一个新的执行上下文。每个函数都拥有自己的执行上下文,但是只有在函数被调用的时候才会被创建。一个程序中可以存在任意数量的函数执行上下文。每当一个新的执行上下文被创建,它都会按照特定的顺序执行一系列步骤。
三、Eval函数执行上下文:运行在eval函数中的代码也获得自己的执行上下文,不常用函数,不建议使用。
执行上下文如何被创建?
执行上下文分两个阶段创建:1)创建阶段;2)执行阶段
一、创建阶段:在任意的JavaScript代码被执行之前,执行上下文处于创建阶段。在创建阶段中总共发生了三件事情:
1.确定this的值,也被称为This Binding;
2.LexicalEnvironment(词法环境)组件被创建。
3.VariableEnvironment(变量环境)组件被创建。
创建阶段
Ⅰ、This Binding:
在全局执行上下文中,this的值指向全局对象,在浏览器中,this的值指向window对象。在函数指向上下文中,this的值取决于函数的调用方式。如果它被一个对象引用调用,那么this的值被设置为该对象,否则this的值被设置为全局对象或undefined(严格模式下)。
Ⅱ、LexicalEnvironment(词法环境):
ES6文档将词法环境定义为:词法环境是一种规范类型,基于ECMAScript代码的词法嵌套结构来定义标识符与特定变量和函数的关联关系(environment record)和可能为空引用(null)的外部词法环境组成。简而言之,词法环境是一个包含标识符变量映射的结构。(这里的标识符表示变量/函数的名称,变量是对实际对象【包含函数类型对象】或原始值的引用)
在LexicalEnvironment(词法环境)中,有两个部分组成:(1)环境记录(environment record):是存储变量和函数声明的实际位置 (2)对外部环境的引用:意味着它可以访问外部词法环境。
LexicalEnvironment(词法环境)有两种类型:
1.全局环境(在全局执行上下文中)是一个没有外部环境的词法环境。全局环境的外部环境引用为null。它拥有一个全局对象(window对象)及其关联的方法和属性(例如数组方法)以及任何用户自定义的全局变量,this的值指向这个全局对象。
2.函数环境,用户在函数中定义的变量被存储在环境记录中,对外部环境的引用可以是全局,也可以是包含内部函数的外部函数环境。
注意:对于函数环境而言,环境记录还包含了一个arguments对象,该对象包含了索引和传递给函数的参数之间的映射以及传递给函数的长度(数量)。
环境记录同样有两种类型:
1.声明性环境记录:存储变量、函数和参数。一个函数环境包含声明性环境记录。
2.对象环境记录:用于定义在全局执行上下文中出现的变量和函数的关联。全局环境包含对象环境记录。
Ⅲ、VariableEnvironmen(变量环境):
它也是一个词法环境,其EnvironmentRecord包含了由VariableStatements在此执行上下文创建的绑定。它具有上面定义的语法环境的所有属性。与LexicalEnvironment的区别在于前者用于存储函数声明和变量(let和const)绑定,而后者仅用于存储变量(var)绑定。
结合实例分析:
let a=10;const b=20;var c;function addFun (e,f){var g =50;return e*f*g;}c = addFun(30,40)/*GlobalExecutionContext = {ThisBinding = <Global Object> //确定thisLexicalEnvironment = {EnvironmentRecord:{Type:'Object' //全局环境//标识符绑定a:<uninitialized>,b:<uninitialized>,addFun:<Func>},outer:<null> //对外部环境的引用}, //词法环境VariableEnvironment = {EnvironmentRecord:{Type:'Object' //全局环境//标识符绑定c:undefined},outer:<null> //对外部环境的引用} //变量环境}FunctionExecutionContext = {ThisBinding = <Global Object> //确定thisLexicalEnvironment = {EnvironmentRecord:{Type:'Declarative' //函数环境//标识符绑定Arguments:{0:30,1:40,length:2}},outer:<GlobalLexicalEnvironment>//对外部环境的引用}, //词法环境VariableEnvironment = {EnvironmentRecord:{Type:'Declarative' //函数环境//标识符绑定g:undefined},outer:<GlobalLexicalEnvironment>//对外部环境的引用} //变量环境}*/
只有在addFun调用的时候才会创建函数执行上下文。创建之初,代码会被扫描并解析变量和函数声明,其中函数声明存储在环境之中,而变量会被设置为undefined(在var情况下)或保持未初始化(在let和const情况下)。这也是为什么可以在声明之前访问var定义的变量(尽管是undefined),但如果在let或const之前访问定义的变量会提示引用错误的原因。
这就是所谓的变量提升。
函数上下文
在函数上下文中,用活动对象(activation object,AO)来表示变量对象。
活动对象和变量对象的区别在于:
1.变量对象(VO)是规范上或者是JS引擎上实现的,并不能在JS环境中直接访问。
2.当进入到一个执行上下文后,这个变量才会被激活,所以叫活动变量(AO),这个时候活动变量上的各种属性才能被访问。
调用函数的时候,会为其创建一个Arguments对象,并自动初始化局部变量arguments,指代该Arguments对象。所有作为参数传入的值都会成为Arguments对象的数组元素。
二、执行阶段分为两个阶段。注:在执行阶段,如果JavaScript引擎在源代码中声明的位置找不到let变量的值,那么将为其分配undefined的值。
Ⅰ、进入执行阶段
此时的变量对象会进行初始化:
1.函数的所有形参:没有实参,属性值设为undefined。
2.函数声明:如果变量对象已经存在相同的属性,则完全替换这个属性。
3.变量声明:如果变量名称跟已经声明的形参或函数相同,则变量声明不会干扰已经存在的属性。
Ⅱ、代码执行
这个阶段会顺序执行代码,修改变量对象的值。
执行阶段总结:
1.全局上下文的变量初始化是全局对象;
2.函数上下文的变量对象初始化只包括Arguments对象;
3.在进入执行上下文时会给变量对象添加形参,函数声明,变量声明等初始属性值
4.在代码执行阶段,会再次修改变量对象的属性值。
转载于:https://www.cnblogs.com/xuxiaoqiangAndHM/p/10514247.html
Javascript执行上下文和执行栈相关推荐
- JavaScript执行上下文和作用域链
执行上下文作用域链 执行上下文(Execution Context):函数执行前进行的准备工作(也称执行上下文环境) 运行 JavaScript 代码的时候,当代码执行进入一个环境时,就会为该环境创建 ...
- 万字干货!详解JavaScript执行过程
作者 | FinGet 责编 | 欧阳姝黎 JS代码的执行,主要分为两个个阶段:编译阶段.执行阶段.本文所有内容基于V8引擎. 前言 v8引擎 v8引擎工作原理: V8由许多子模块构成,其 ...
- 前端进击的巨人(一):执行上下文与执行栈,变量对象
写在开篇 已经不敢自称前端小白,曾经吹过的牛逼总要一点点去实现. 正如前领导说的,自己喝酒吹过的牛皮,跪着都得含着泪去实现. 那么没有年终完美总结,来个新年莽撞开始可好. 进击巨人系列开篇,不忘初心, ...
- 前端进击的巨人(1):执行上下文与执行栈,变量对象
(给前端大全加星标,提升前端技能) 作者:以乐之名 https://segmentfault.com/a/1190000017890535 写在开篇 已经不敢自称前端小白,曾经吹过的牛逼总要一点点去实 ...
- 2.JS执行上下文和变量对象
文章目录 执行上下文栈 函数上下文 变量对象 执行过程 进入执行上下文 代码执行 两个例子 1 2 JS 是单线程语言,因此执行顺序是顺序执行,不过 JS 引擎在执行 JS 代码的时候并不是逐行执 ...
- Javascript中你必须理解的执行上下文和调用栈
执行上下文在 JavaScript 是非常重要的基础知识,想要理解 JavaScript 的执行过程,执行上下文是你必须要掌握的知识.否则只能是知其然不知其所以然. 理解执行上下文有什么好处呢? 它可 ...
- 了解Javascript中的执行上下文和执行堆栈
By Sukhjinder Arora | Aug 28, 2018 原文 如果你是或者你想要成为一名js开发者,那么你必须了解js程序内部的运作.理解执行上下文和执行堆栈对于理解js的其它概念(如提 ...
- # JavaScript中的执行上下文和队列(栈)的关系?
原文:What is the Execution Context & Stack in JavaScript? git地址:JavaScript中的执行上下文和队列(栈)的关系? 导读:以前总 ...
- javascript --执行上下文,作用域
执行上下文 顾名思意就知道他是动态的,只在代码运行的时候产生 作用域 顾名思意就知道它是一个"领域",并且这个"领域"在一开始就规划好, 不会在改, var d ...
最新文章
- Silverlight学习之——如何在 Silverlight 中使用 Deep Zoom
- java struts2 漏洞复现合集
- python用户输入算式并计算_Python 70行代码实现简单算式计算器
- 00018计算机应用基础2019年4月,2019年4月自考计算机应用基础考前试题和答案00018.pdf...
- pandas 固定值 增加一列_pandas入门详细教程(附导图)
- 图方法:寻找无向图联通子集的JAVA版本
- python中变量和函数的区别_关于python中带下划线的变量和函数 的意义
- 模板:多项式乘法(FFTNTT)
- 玩转异步 JS :async/await 简明教程(附视频下载)
- 在用v-for时又想用v-if进行判断是否生产内容
- java集合(一):List、Iterator、Array、ArrayList、LinkList
- amd opencl使用低版本驱动
- pm入门-需求调研/竞品分析/应用工具简介
- idea运行SSM项目配置tomcat及启动
- 微信公众号(订阅号)如何开通付费功能?
- Spring Boot 通过 Mvc 扩展方便进行货币单位转换
- 中国电信官方提醒:7类短信诈骗须警惕
- 公司财务笔记-岭南学院辅修
- [附源码]计算机毕业设计JAVA校园征兵及退役复原管理系统
- 去掉设备和驱动器的百度网盘
热门文章
- Video 对象方法 canPlayType()
- php定时任务(自己)
- JAVA记录-Servlet介绍
- WinForm - 两个窗体之间的方法调用
- SharePoint 2010 技术参数(整理)
- python分割字符串输出_python字符串分割
- 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器,sqlserver
- Matlab矩阵、元胞数组的合并拼接
- AUTOSAR从入门到精通100讲(三十八)-通信网络中的⽐特和帧同步技术
- python27怎么使用_pygtk:glade的使用(针对python27的第一个例子)