位置: 编程技术 - 正文

跟我学习javascript的执行上下文(java 视频教程)

编辑:rootadmin

推荐整理分享跟我学习javascript的执行上下文(java 视频教程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:java教程,java教程,java script怎么学,java script入门,java script怎么学,java script,java script,java learning,内容如对您有帮助,希望把文章链接给更多的朋友!

在这篇文章里,我将深入研究JavaScript中最基本的部分——执行上下文(execution context)。读完本文后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如何决定的。

1、EC—执行环境或者执行上下文

每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文(好高大上的概念啊)。

javascript中,EC分为三种:

全局级别的代码 ?? 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境。 函数级别的代码 ??当执行一个函数时,运行函数体中的代码。 Eval的代码 ?? 在Eval函数内运行的代码。

EC建立分为两个阶段:进入执行上下文(创建阶段)和执行阶段(激活/执行代码)。

1)、进入上下文阶段:发生在函数调用时,但是在执行具体代码之前(比如,对函数参数进行具体化之前) 创建作用域链(Scope Chain)创建变量,函数和参数。求”this“的值。2)、执行代码阶段: 变量赋值函数引用解释/执行其他代码。我们可以将EC看做是一个对象。

现在让我们看一个包含全局和函数上下文的代码例子:

很简单的例子,我们有一个被紫色边框圈起来的全局上下文和三个分别被绿色,蓝色和橘色框起来的不同函数上下文。只有全局上下文(的变量)能被其他任何上下文访问。

你可以有任意多个函数上下文,每次调用函数创建一个新的上下文,会创建一个私有作用域,函数内部声明的任何变量都不能在当前函数作用域外部直接访问。在上面的例子中,函数能访问当前上下文外面的变量声明,但在外部上下文不能访问内部的变量/函数声明。为什么会发生这种情况?代码到底是如何被解释的?

2、ECS—执行上下文栈

一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。

压栈:全局EC—>局部EC1—>局部EC2—>当前EC 出栈:全局EC<—局部EC1<—局部EC2<—当前EC

我们可以用数组的形式来表示环境栈:

每次控制器进入一个函数(哪怕该函数被递归调用或者作为构造器),都会发生压栈的操作。过程类似javascript数组的push和pop操作。

浏览器里的JavaScript解释器被实现为单线程。这意味着同一时间只能发生一件事情,其他的行文或事件将会被放在叫做执行栈里面排队。下面的图是单线程栈的抽象视图:

我们已经知道,当浏览器首次载入你的脚本,它将默认进入全局执行上下文。如果,你在你的全局代码中调用一个函数,你程序的时序将进入被调用的函数,并穿件一个新的执行上下文,并将新创建的上下文压入执行栈的顶部。

如果你调用当前函数内部的其他函数,相同的事情会在此上演。代码的执行流程进入内部函数,创建一个新的执行上下文并把它压入执行栈的顶部。浏览器将总会执行栈顶的执行上下文,一旦当前上下文函数执行结束,它将被从栈顶弹出,并将上下文控制权交给当前的栈。下面的例子显示递归函数的执行栈调用过程:

这代码调用自己三次,每次给i的值加一。每次foo函数被调用,将创建一个新的执行上下文。一旦上下文执行完毕,它将被从栈顶弹出,并将控制权返回给下面的上下文,直到只剩全局上下文能为止。

有5个需要记住的关键点,关于执行栈(调用栈):

单线程。 同步执行。 一个全局上下文。 无限制函数上下文。 每次函数被调用创建新的执行上下文,包括调用自己。

3、VO—变量对象

每一个EC都对应一个变量对象VO,在该EC中定义的所有变量和函数都存放在其对应的VO中。

VO分为全局上下文VO(全局对象,Global object,我们通常说的global对象)和函数上下文的AO。

1)、进入执行上下文时,VO的初始化过程具体如下:

函数的形参(当进入函数执行上下文时)—— 变量对象的一个属性,其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined;

函数声明(FunctionDeclaration, FD) —— 变量对象的一个属性,其属性名和值都是函数对象创建出来的;如果变量对象已经包含了相同名字的属性,则替换它的值;

变量声明(var,VariableDeclaration) —— 变量对象的一个属性,其属性名即为变量名,其值为undefined;如果变量名和已经声明的函数名或者函数的参数名相同,则不会影响已经存在的属性。 注意:该过程是有先后顺序的。

跟我学习javascript的执行上下文(java 视频教程)

2)、 执行代码阶段时,VO中的一些属性undefined值将会确定。

4、AO活动对象

在函数的执行上下文中,VO是不能直接访问的。它主要扮演被称作活跃对象(activation object)(简称:AO)的角色。 这句话怎么理解呢,就是当EC环境为函数时,我们访问的是AO,而不是VO。

AO是在进入函数的执行上下文时创建的,并为该对象初始化一个arguments属性,该属性的值为Arguments对象。

FD的形式只能是如下这样:

当函数被调用是executionContextObj被创建,但在实际函数执行之前。这是我们上面提到的第一阶段,创建阶段。在此阶段,解释器扫描传递给函数的参数或arguments,本地函数声明和本地变量声明,并创建executionContextObj对象。扫描的结果将完成变量对象的创建。

内部的执行顺序如下:

1、查找调用函数的代码。

2、执行函数代码之前,先创建执行上下文。 3、进入创建阶段:

初始化作用域链: 创建变量对象: 创建arguments对象,检查上下文,初始化参数名称和值并创建引用的复制。 扫描上下文的函数声明:为发现的每一个函数,在变量对象上创建一个属性(确切的说是函数的名字),其有一个指向函数在内存中的引用。如果函数的名字已经存在,引用指针将被重写。 扫面上下文的变量声明:为发现的每个变量声明,在变量对象上创建一个属性——就是变量的名字,并且将变量的值初始化为undefined,如果变量的名字已经在变量对象里存在,将不会进行任何操作并继续扫描。 求出上下文内部“this”的值。

4、激活/代码执行阶段: 在当前上下文上运行/解释函数代码,并随着代码一行行执行指派变量的值。

示例

1、具体实例

当调用foo()时,创建状态像下面这样:

真如你看到的,创建状态负责处理定义属性的名字,不为他们指派具体的值,以及形参/实参的处理。一旦创建阶段完成,执行流进入函数并且激活/代码执行阶段,看下函数执行完成后的样子:

2、VO示例:

进入执行上下文时,

执行代码时:

对于以上的过程,我们详细解释下。

在进入上下文的时候,VO会被填充函数声明; 同一阶段,还有变量声明“x”,但是,正如此前提到的,变量声明是在函数声明和函数形参之后,并且,变量声明不会对已经存在的同样名字的函数声明和函数形参发生冲突。因此,在进入上下文的阶段,VO填充为如下形式:

执行代码阶段,VO被修改如下:

如下例子再次看到在进入上下文阶段,变量存储在VO中(因此,尽管else的代码块永远都不会执行到,而“b”却仍然在VO中)

3、AO示例:

当进入test()的执行上下文时,它的AO为:

由此可见,在建立阶段,VO除了arguments,函数的声明,以及参数被赋予了具体的属性值,其它的变量属性默认的都是undefined。函数表达式不会对VO造成影响,因此,(function x() {})并不会存在于VO中。

当执行 test()时,它的AO为:

可见,只有在这个阶段,变量属性才会被赋具体的值。

5、提升(Hoisting)解密

在之前的JavaScript Item中降到了变量和函数声明被提升到函数作用域的顶部。然而,没有人解释为什么会发生这种情况的细节,学习了上面关于解释器如何创建active活动对象的新知识,很容易明白为什么。看下面的例子:

我们能回答下面的问题:

1、为什么我们能在foo声明之前访问它? 如果我们跟随创建阶段,我们知道变量在激活/代码执行阶段已经被创建。所以在函数开始执行之前,foo已经在活动对象里面被定义了。

2、foo被声明了两次,为什么foo显示为函数而不是undefined或字符串? 尽管foo被声明了两次,我们知道从创建阶段函数已经在活动对象里面被创建,这一过程发生在变量创建之前,并且如果属性名已经在活动对象上存在,我们仅仅更新引用。 因此,对foo()函数的引用首先被创建在活动对象里,并且当我们解释到var foo时,我们看见foo属性名已经存在,所以代码什么都不做并继续执行。

3、为什么bar的值是undefined? bar实际上是一个变量,但变量的值是函数,并且我们知道变量在创建阶段被创建但他们被初始化为undefined。

标签: java 视频教程

本文链接地址:https://www.jiuchutong.com/biancheng/384648.html 转载请保留说明!

上一篇:跟我学习javascript的循环(java教程)

下一篇:每天一篇javascript学习小结(String对象)(每天一篇小练笔主题)

  • 如何查商品税收分类编码
  • 进口设备退税如何账务处理?
  • 员工买东西自己垫付的钱怎么做账
  • 车辆备注栏备注怎么填
  • 广告公司属于服务企业吗
  • 期末现金及现金等价物余额公式
  • 发票能加盖公章吗
  • 销售货物未开发怎么处理
  • 菜场摊位租赁合同
  • 银行贷款损失的认定标准
  • 企业劳务发票怎么开,税率是多少
  • 船票能开发票吗
  • 公司车辆高速费用能开增值税专用发票吗
  • 农产品发票抵扣需要勾选吗
  • 网上勾选认证每月时间要求
  • 行政事业单位会计基础工作规范
  • etc在充值后未索取可以再次索取吗
  • 减半征收城建税文件
  • 专用发票上注明的税额是什么
  • 加权平均数是什么意思的权
  • 领用库存商品的消费税
  • 预付保险费属于什么会计科目
  • 企业所得税以前年度所得调整
  • 收到利息收入会计分录怎么写
  • 用户登录系统后首先进入什么
  • 价外费用含义
  • 筹建期间费用计什么科目
  • 差额部分 扣除部分
  • win10系统安装详细步骤
  • vue实现打印
  • 经营租赁固定资产体现实质重于形式
  • 缴住房公积金会计分录怎么写
  • 会计科目备抵科目都有哪些
  • 职工教育经费计入管理费用吗
  • 独立费用包括
  • 黄金旧料卖出收据怎么写
  • php收发邮件
  • 浅谈socket同步和异步、阻塞和非阻塞、I/O模型
  • 全局平均池化(GAP)层
  • 我的十年怎么写
  • 人工智能lisp
  • 企业所得税应纳税所得额300万以下
  • 普通发票收款人填管理员可以吗
  • 非财政补助结余分配和非财政拨款结余分配
  • 亏损弥补规定
  • EOFError:EOF when reading a line
  • 帝国cms使用手册
  • sql serverjdbc
  • 小规模纳税人企业所得税优惠政策最新2023
  • mysql8.0存储过程
  • 建筑公司收到劳务发票会计分录
  • 执行企业会计制度是什么意思
  • 银行卡频繁小额转账
  • 融资购入的固定资产如何记账
  • 企业所得税什么时候计提
  • 去年多计提工资今年怎么进行损益调整
  • 给客户优惠货款怎么写
  • 对方多开发票怎么处理?
  • 跨年的费用
  • 支付广告费属于进项还是销项
  • 工会经费支出范围
  • 员工差旅费会计分录
  • 财付通交易手续费多少
  • 增强型图形文件
  • window系统怎么复制粘贴
  • windows10日历没有显示农历
  • winhlp32.exe - winhlp32是什么进程
  • Centos 6.4 64位版命令行下设置无线网卡教程
  • windows 8
  • Android 近百个项目的源代码
  • Unity3D游戏开发引擎
  • 如何ssh登陆
  • xcopy命令怎么用
  • bootstrap范例
  • highcharts update
  • jquery限制字符长度
  • 落实与什么动词搭配
  • 夫妻相聚
  • 如果快递没有按时发货东西变质怎么办
  • 1950土地改革后土地所有权
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设