摘要:用伪代码来表示函数未进入执行阶段之前,变量对象中的属性都不能访问但是进入执行阶段之后,变量对象转变为了活动对象。全局上下文中,变量对象就是本身。函数上下文中,变量对象包括函数声明,变量声明。
概述
JavaScript 的可执行代码,具有执行上下文,而每个上下文包括以下 3 个属性:
变量对象(variable object, 简称 VO)
作用域链(scope chain)
this
变量对象提供了当前环境所需的变量和函数
作用域链用于保证 JS 中变量和函数有序地访问
this 为函数提供了执行者对象
一个上下文的执行周期可以用下图示意:
本文就来介绍执行上下文中的变量对象。
那什么是变量对象呢?先看定义:
变量对象是与执行上下文相关的数据作用域,用于存储执行上下文中的变量和函数声明。
不同的执行上下文,变量对象会有一些差别。接下来就分别针对不同的上下文讨论其区别。
一、全局上下文全局对象(Global object) 是在进入任何执行上下文之前就已经创建了的对象;
这个对象只存在一份,它的属性在程序中任何地方都可以访问,全局对象的生命周期终止于程序退出那一刻。
在全局代码的上下文执行环境中,变量对象就是全局对象,在浏览器中,就是 window 对象。
此时,我们可以用 this 和 self 来访问到全局对象,也就是它本身
console.log(this) // window console.log(self) // window
其次,全局对象初始创建阶段将 Math、String、Date、parseInt 等函数作为自身方法,还会把全局变量作为自己的属性。
用伪代码表示就是:
global = { Math: <...> Date: <...> window: global // 引用自身 }二、函数上下文
我们已经知道,变量对象存储量执行上下文中的函数声明和变量,在函数上下文中,多了 arguments(函数参数列表), 一个类数组对象。
用伪代码来表示:
VO = { arguments: Arguments, variables: undefine, functionName:}
函数未进入执行阶段之前,变量对象中的属性都不能访问!但是进入执行阶段之后,变量对象转变为了活动对象(activation object)。
所以,在函数上下文中,我们将活动对象(activation object)作为变量对象,活动对象最开始只包含一个变量就是 arguments 对象(这个对象是全局环境中没有的)。
arguments 的属性值 Arguments 它包括如下属性:
callee — 谁调用了本函数
length — 真正传递的参数个数
properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)
三、创建过程我们再一次来看这个过程图:
创建阶段
全局对象初始化的时候,就将变量对象引用了自身。
而函数的创建却有需要注意的地方。
函数在创建阶段就创建了变量对象
其中,变量对象包括:
当前函数的参数列表,建立 Arguments 对象。
所有的函数声明(不包括函数表达式哦!),直接指向函数
所有的变量声明(var 声明的变量),默认为 undefined
进入执行上下文时,函数声明和变量声明都会提前,这就是声明提升,但是变量声明的值都是undefined,而函数声明的变量已经可以指向函数。变量声明的优先级最低。
看下面这段代码:
function foo(a, b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } foo(10);
当进入函数 foo 时,其变量对象的表现形式为:
VO = { arguments: { 0: 10, 1: undefined, length: 1 } c: undefined, d:, e: undefined, }
x 是函数表达式,所以不在变量对象当中,e 变量引用的值也是函数表达式,所以变量 e 本身是声明,所以在变量对象当中。
执行阶段
当前进入执行阶段,变量对象激活成活动对象,函数会顺序执行代码,改变变量对象的值:
以上代码就变成:
AO = { arguments: { 0: 10, 1: undefined, length: 1 } c: 10, d:, e: , }
接下来看一段代码:
console.log(foo); function foo() { console.log("123") } var foo = "456";
以上会打印函数,是因为:
变量优先处理函数声明,再是变量声明。
再看一段代码:
if (true) { var a = 1; } else { var b = 2; } console.log(a); // 1 console.log(b); // undefined
虽然 else 中的代码永远不会被执行,但是 b 的变量声明在执行之前就默认被设置成 undefined了。
总结执行上下文包括三个属性,变量对象,作用域链,this, 不同的执行上下文,变量对象是有区别的。
全局上下文中,变量对象就是本身。
函数上下文中,变量对象包括:arguments, 函数声明,变量声明。在函数创建阶段,变量对象有默认值,进入执行阶段后,变量对象会被激活成活动对象,然后变量对象的值被顺序改变。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/98411.html
摘要:对象数组初始化表达式,闯关记之上文档对象模型是针对和文档的一个。闯关记之数组数组是值的有序集合。数组是动态的,根闯关记之语法的语法大量借鉴了及其他类语言如和的语法。 《JavaScript 闯关记》之 DOM(下) Element 类型 除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了。Element 类型用于表现 XML 或 HTML 元素...
摘要:下面,让我们以一个函数的创建和激活两个时期来讲解作用域链是如何创建和变化的。这时候执行上下文的作用域链,我们命名为至此,作用域链创建完毕。 JavaScript深入系列第五篇,讲述作用链的创建过程,最后结合着变量对象,执行上下文栈,让我们一起捋一捋函数创建和执行的过程中到底发生了什么? 前言 在《JavaScript深入之执行上下文栈》中讲到,当JavaScript代码执行一段可执行代...
摘要:深入系列第四篇,具体讲解执行上下文中的变量对象与活动对象。下一篇文章深入之作用域链本文相关链接深入之执行上下文栈深入系列深入系列目录地址。 JavaScript深入系列第四篇,具体讲解执行上下文中的变量对象与活动对象。全局上下文下的变量对象是什么?函数上下文下的活动对象是如何分析和执行的?还有两个思考题帮你加深印象,快来看看吧! 前言 在上篇《JavaScript深入之执行上下文栈》中...
摘要:本计划一共期,每期重点攻克一个面试重难点,如果你还不了解本进阶计划,点击查看前端进阶的破冰之旅本期推荐文章深入之执行上下文栈和深入之变量对象,由于微信不能访问外链,点击阅读原文就可以啦。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导) 本周正式开始前端进阶的第一期,本周的主题是调用堆栈,今天是第二天。 本计划一共28期,每期...
摘要:深入系列第七篇,结合之前所讲的四篇文章,以权威指南的为例,具体讲解当函数执行的时候,执行上下文栈变量对象作用域链是如何变化的。前言在深入之执行上下文栈中讲到,当代码执行一段可执行代码时,会创建对应的执行上下文。 JavaScript深入系列第七篇,结合之前所讲的四篇文章,以权威指南的demo为例,具体讲解当函数执行的时候,执行上下文栈、变量对象、作用域链是如何变化的。 前言 在《Jav...
摘要:引子前不久我建立的技术群里一位问了一个这样的问题,她贴出的代码如下所示执行结果如下所示第一个第二个这是一个令人诧异的结果,为什么第一个弹出框显示的是,而不是呢这种疑惑的原理我描述如下一个页面里直接定义在标签下的变量是全局变量即属于对象的变量 1) 引子 前不久我建立的技术群里一位MM问了一个这样的问题,她贴出的代码如下所示: var a = 1; function hehe...
阅读 2288·2021-11-24 09:38
阅读 1984·2021-11-22 14:44
阅读 1149·2021-07-29 13:48
阅读 2613·2019-08-29 13:20
阅读 1115·2019-08-29 11:08
阅读 2044·2019-08-26 10:58
阅读 1262·2019-08-26 10:55
阅读 3148·2019-08-26 10:39