位置: 编程技术 - 正文

跟我学习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对象)(每天一篇小练笔主题)

  • 税务师考试各科老师推荐
  • 公司购买新车购置税是否可以抵扣呢
  • 个税什么情况可以抵扣
  • 未收回的货款是企业资产吗
  • 预缴税款如何抵扣苗木款
  • 财务记账之后是否必须审核
  • 公司给员工租的宿舍怎么交税
  • 挖掘机要交多少个人所得税
  • 以房抵顶工程款有效吗
  • 发票一定要填数量吗
  • 固定资产缩水
  • 在建工程领用原材料的账务处理
  • 结存材料物资会计分录怎么做?
  • 被收购的收入计什么科目
  • 广告费可以预提吗
  • 发票先收到下个月才付款
  • 从公司账户转给个人账户取出来发给员工做过节费
  • 奖励给优质供应商会计处理怎么做?
  • 个税手续费返还比例
  • 非独立核算的分公司注销流程
  • 开了增值税发票不确认收入可以吗
  • 大型超市税收分析报告
  • 所有的固定资产都有残值率吗
  • 查账征收改为核定征收需要什么资料
  • macbook触摸板如何拖动
  • 2023个人出租房屋房产税
  • 公司增资扩股需要考略公司资产吗
  • 现在windows11
  • 注销企业基本户需要先注销一般户吗
  • PHP:pg_escape_string()的用法_PostgreSQL函数
  • 返点收入怎么会计分录
  • 固定资产后续支出一律计入固定资产成本
  • 黑沙滩是什么意思
  • 营改增允许从销售额中扣
  • 非正常损失的存货进项税额转出
  • 增值税纳税人如何界定
  • opencv制作训练数据集
  • named-config
  • 代扣费用会计分录
  • 固定资产处置缴纳增值税政策依据
  • 增值税留抵税额退税政策
  • 汽车销售公司购置税账务处理
  • 未达起征点怎么填申报表
  • 临时工享受的福利有哪些
  • 交易性金融资产处置时的会计核算步骤
  • sqlyog提示
  • php网站根目录
  • sqlserver连接到服务器登录名
  • 收到生育津贴会计分离
  • 代数分配法的优缺点和适用范围
  • 分公司可以在银行贴现吗
  • 股权和出资的关系
  • 管理费用冲减其他费用
  • 职工福利费如何入账
  • 2020年防洪基金计算公式
  • 税金及附加如何预测
  • 采购业务 货物收到 发票收到
  • 抵扣与扣除的区别
  • 《关于工资总额组成的规定》第四条
  • centos下安装虚拟机
  • 史上最快的速度
  • Win Server 2003 使用技巧图解
  • 利用()可以对系统进行全面的设置
  • windows xp自带
  • wdsvc.exe - wdsvc 是什么进程
  • win7360安全卫士有必要装吗
  • Win10打开或关闭系统图标里开怎么灰色的
  • 如何关闭win10自动升级win11
  • nodejs使用视频教程
  • svn下载项目
  • cocos2d原理
  • 安卓app开发框架模板
  • linux中shell的作用
  • vue项目简介
  • 国家税务总局全国增值税发票官网
  • 关于研发费用的审计程序,下列说法中错误的是
  • 建筑企业税务清算流程图
  • 湖南地税电话号码
  • 个人所得税选择那种方式更好
  • 济南房产税如何计算公式
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设