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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rsa加密算法python_模拟新浪微博登录(Python+RSA加密算法)

声明&#xff1a;由于本人使用用的是Python语言&#xff0c;以下内容就在该语言下进行解释说明。有使用Java语言的可以参考IT男杂记(http://marspring.mobi/http-client-weibo/)正文&#xff1a;PC登录新浪微博时&#xff0c;在客户端用js预先对用户名、密码都进行了加密&#…

基于swagger进行接口文档的编写

0. 前言 近期忙于和各个银行的代收接口联调&#xff0c;根据遇到的问题&#xff0c;对之前编写的接口进行了修改&#xff0c;需求收集和设计接口时想到了方方面面&#xff0c;生产环境下还是会遇到意想不到的问题&#xff0c;好在基本的执行逻辑已确定&#xff0c;因此只是对接…

教程:编写自己的CDI扩展

今天&#xff0c;我将向您展示如何编写CDI扩展。 CDI提供了一种扩展功能的简便方法&#xff0c;例如 添加自己的范围&#xff0c; 启用Java核心类进行扩展&#xff0c; 使用注释元数据进行扩充或修改&#xff0c; 以及更多。 在本教程中&#xff0c;我们将实现一个扩展&a…

c调用python脚本 效率,尝试用C调用Python脚本#

我正在制作一个迷你Python IDE来好玩。为什么不。所以我希望能够从C调用一个python脚本&#xff0c;现在我只测试一个简单的场景。我知道这不是专业IDE的工作原理。在private void Run_Click(object sender, EventArgs e){run_cmd("C:/Python34/python.exe", "C…

Hyhyhy – 专业的 HTML5 演示文稿工具

Hyhyhy 是创建好看的 HTML5 演示文档的工具。它具备很多的特点&#xff1a;支持 Markdown&#xff0c;嵌套幻灯片&#xff0c;数学排版&#xff0c;兼容性&#xff0c;语法高亮&#xff0c;使用 Javascript API &#xff0c;方便的骨架。它支持 Firefox 2 , Safari 3 , Opera 9…

POJ 1258 Agri-Net (最小生成树)

题目&#xff1a; Description Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course. Farmer John ordered a high speed connection for his farm a…

python人工智能炒期货_学会用Python结合人工智能尝试预测股票,下一个股神就是你!...

股票市场涨涨跌跌&#xff0c;好像毫无规律&#xff0c;但有一些人却凭借自己的直觉掌握了一些特殊规律&#xff0c;从而实现在股票上的实现斩获。现在在人工智能时代&#xff0c;PythonAI框架&#xff0c;无疑会利用人工智能优势可以对股票市场进行特征学习&#xff0c;抓取比…

JAX-RS 2.0中的透明PATCH支持

PATCH方法是最不受欢迎的HTTP方法之一&#xff0c;因为直到最近才真正没有一种标准的PATCH格式。 一段时间以来&#xff0c;它已经针对JSON进行了标准化&#xff0c;因此有很多库可以为您完成繁重的工作。 出于本博客的目的&#xff0c;我将使用json-patch&#xff0c;尽管可以…

Java开发知识之Java的枚举

Java开发知识之Java的枚举 一丶什么是枚举 枚举可以理解为就是常量,在Java中我们定义常量.都是用 final语句. C中都是用const关键字. 枚举跟C概念都是一样的.就是特定的常量而已. 二丶Java中的枚举 java中的常量.一般都是final定义.但是我们讲过.final定义的常量.初始化的时候可…

linux php7 mongodb,CentOS 7下安装配置PHP7跟LAMP及MongoDB和Redis

CentOS 7下安装配置PHP7跟LAMP及MongoDB和Redis我是想能yum就yum&#xff0c;所有软件的版本一直会升级&#xff0c;注意自己当时的版本是不是已经更新了。首先装CentOS 7装好centos7后默认是不能上网的cd /etc/sysconfig/network-scripts/找到形如ifcfg-enp0s3的文件&#xff…

【汇总目录】C#

[2019年04月29日] C# textbox 自动滚动 [2019年02月07日] C#利用VUDP.cs开发网络通讯应用程序 [2019年02月06日] C#利用VINI.cs操作INI文件 [2018年12月19日] 控件数组批量生成控件 转载于:https://www.cnblogs.com/velscode/p/10535101.html

基于 Bootstrap 的响应式后台管理面板

你想建立一个后台管理面板或者分析仪表板吗&#xff1f;不需从头开始&#xff0c;Keen IO Bootstrap 是一个响应式的仪表盘模板&#xff0c;可以帮助你在几分钟内呈现数据&#xff0c;让你可以创建一个有吸引力的&#xff0c;定制的分析仪表板&#xff0c;随时可以展现给你的团…

Java:AspectJ的异常翻译

在这篇博客文章中&#xff0c;我描述了如何使用AspectJ自动将一种异常类型转换为另一种异常类型。 问题 有时&#xff0c;我们处于必须将异常&#xff08;通常由第三方库引发&#xff09;转换为另一种异常的情况。 假设您使用的是诸如hibernate之类的持久性框架&#xff0c;并…

sparkstreaming监听hdfs目录_大数据系列之Spark Streaming接入Kafka数据

Spark Streaming官方提供Receiver-based和Direct Approach两种方法接入Kafka数据&#xff0c;本文简单介绍两种方式的pyspark实现。1、Spark Streaming接入Kafka方式介绍Spark Streaming 官方提供了两种方式读取Kafka数据&#xff1a;一是Receiver-based Approach。该种读取模式…

php职业认证,如何用 PHP 进行 HTTP 认证

PHP 的 HTTP 认证机制在 PHP 以 Apache 模块方式运行时才有效&#xff0c;因此该功能不适用于 CGI 版本。在 Apache 模块的 PHP 脚本中&#xff0c;可以用 header() 函数来向客户端浏览器发送“Authentication Required”信息&#xff0c;使其弹出一个用户名/密码输入窗口。当用…

时间服务器

时间服务器配置&#xff1a; 1 安装软件包: [rootlocalhost ~]# yum install ntp –y 2 修改配置文件 [rootlocalhost ~]# vim /etc/ntp.conf # 允许内网其他机器同步时间 192.168.1.0该网段 restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap 允许任何ip的客户机都可以…

使用 HTML5 Canvas 绘制出惊艳的水滴效果

HTML5 在不久前正式成为推荐标准&#xff0c;标志着全新的 Web 时代已经来临。在众多 HTML5 特性中&#xff0c;Canvas 元素用于在网页上绘制图形&#xff0c;该元素标签强大之处在于可以直接在 HTML 上进行图形操作&#xff0c;具有极大的应用价值。 这里分享一个惊艳的 Canva…

Java EE 8:社区想要什么?

在进行了之前的两次社区调查之后&#xff0c;第一次调查于2013年12月发布&#xff0c;第二次调查于2014年1月发布&#xff0c;Oracle呼吁企业社区对Java EE 8进行第三次也是最后一次调查 。该调查的截止日期为2014年3月24日&#xff0c;12日。太平洋时间。 值得注意的是&#…

mysql 字符串类型 char varchar

字符类型用在存储名字、邮箱地址、家庭住址等描述性数据 char指的是定长字符&#xff0c;varchar指的是变长字符 #官网&#xff1a;https://dev.mysql.com/doc/refman/5.7/en/char.html #注意&#xff1a;char和varchar括号内的参数指的都是字符的长度#char类型&#xff1a;定长…

二叉树遍历规则

树的遍历顺序大体分为三种&#xff1a;前序遍历&#xff08;先根遍历、先序遍历&#xff09;&#xff0c;中序遍历&#xff08;中根遍历&#xff09;&#xff0c;后序遍历&#xff08;后根遍历&#xff09;。 如图所示二叉树&#xff1a; 前序遍历&#xff1a;前序遍历可以记为…