一个热爱技术的菜鸟...用点滴的积累铸就明日的达人

正文

  在上一篇文章中讲解了JavaScript内存模型,其中有提到执行上下文与变量对象的概念。对于JavaScript开发者来说,理解执行上下文与变量对象的基本理论知识,是理解闭包,原型链的关键所在(闭包与原型链会在接下来的文章中介绍)。本篇文章就带你走进JavaScript的执行上下文与变量对象,由于本人才疏学浅,若有什么表述有误的地方,欢迎各位看官能够指点一二,在此不胜感激...

  在阅读这边文章之前,默认您已经掌握了JavaScript的基本概念、栈堆等基本数据结构以及计算机基本理论基础,如有了解欠缺,请移步相关博客后再阅读本文。

一、执行上下文

  JavaScript执行程序的时候,会首先创建一个全局的执行上下文,将其放入栈中,成为栈底。而后每次执行一个函数的时候,都会去创建一个当前函数的执行上下文,然后将其压入栈中,当函数结束或者返回的时候,再从栈中弹出当前函数的执行上下文。执行上下文其实就是函数的执行环境,与Java中的栈帧很像,但是与Java不同的是,由于JavaScript是单线程的,所以JavaScript只有一个栈,对所有的执行上下文压栈与出栈都是相对与同一个栈。

  执行上下文的生命周期包含三个部分:创建阶段、代码执行阶段,执行完毕阶段

  • 创建阶段:在这个阶段中,执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向
  • 代码执行阶段:创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。
  • 执行完毕阶段:执行完毕之后,就会开始将执行上下文出栈,随后释放掉所占用的内存

  下面用图解的方式来描述一下执行上下文的压栈与出栈的步骤,首先先看一段程序

  1. function method_a() {
  2. method_b();
  3. method_c();
  4. }
  5.  
  6. function method_b() {
  7.  
  8. }
  9.  
  10. function method_c() {
  11. method_d();
  12. }
  13.  
  14. function method_d() {
  15.  
  16. }
  17.  
  18. method_a();

  在开始执行程序的时候,会首先创建一个global的全局执行上下文,将其压入栈中

  随后执行method_a()的时候,会创建一个method_a的执行上下文,将其压入栈中

  而后,开始执行method_a()函数中的代码,当执行到第一行的时候,发现要执行method_b()这个函数,所以又开始创建一个method_b的执行上下文,将其压入栈中

  顺利的执行完method_b()函数代码之后,将method_b的执行环境出栈,随后继续执行method_a()函数剩下的代码,发现要执行method_c()函数,所以继续创建method_c的执行上下文,将其压入栈中

  在执行method_c()函数的时候,发现又要执行method_d()函数,所以又要创建method_d的执行上下文,随后执行完method_d()之后,将其出栈,再之后method_c出栈,method_a出栈,最后剩余global执行上下文

  至此,JavaScript中的执行上下文概念介绍完毕...

二、变量对象(VO)

  在介绍执行上下文的创建阶段的时候,有提到变量对象这个概念...本节先来重点了解一下变量对象。变量对象的创建,依次经历了以下几个过程。

  • 建立arguments对象(参数对象,当某个函数接收参数的时候,会将参数封装成arguments对象)
  • 检查当前上下文的函数声明,也就是使用function声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在的内存地址的引用。如果函数名的属性已存在,那么该属性将会被新的引用所覆盖。
  • 检查当前上下文的变量声明,对于每一个变量声明,变量对象会以变量名建立一个属性,属性值为undefined。如果变量名属性已存在,则会直接跳过,原属性值保持不变(这样是为了防止将同名的函数名覆盖)

  在上面的规则中可以看出,function声明会比var声明优先级更高一点,接下来看一个demo,借此来学习与验证一下上述命题

  1. function method(num1, num2) {
  2.  
  3. console.log(arguments);
  4. console.log(num1, num2);
  5. console.log(vara, func);
  6. console.log(func());
  7.  
  8. var vara = 10;
  9. console.log(vara);
  10.  
  11. function func() {
  12. return 1;
  13. }
  14.  
  15. function func() {
  16. return 2;
  17. }
  18.  
  19. }
  20.  
  21. method(1, 2);

  输出结果如下

  1. { '0': 1, '1': 2 }
  2. 1 2
  3. undefined [Function: func]
  4. 2
  5. 10

  首先输出的是arguments对象,通过与第二行输出num1,num2对比可知,argument对象是一种key-value格式的对象,其中key从0开始逐步递增,value依次对应着传入参数。

  随后根据变量声明与函数声明的规则,由于变量声明,会在执行上下文创建阶段为变量赋值undefined,而函数声明,会在执行上下文创建阶段为函数变量赋值指向该函数的引用地址。故第三行输出结果为 undefined 与 [Function:func]

  又由于代码中声明了两个func函数,为了验证是否存在函数覆盖现象,打印输出func()的结果,输出结果为2,则意味着,第二个定义的func函数,在执行上下文阶段,覆盖了一开始的func函数。

  最后给vara赋值10,随即输出vara,得到10

三、OV与AO

  在初学JavaScipt中,总会有同学对变量对象与活动对象弄混,为此解释一下这两个名词。在执行上下文建立的阶段会创建变量对象,变量对象中保存arguments,function声明的函数,var声明的变量,具体的第二节已经介绍,在此不做过多阐述。当执行上下文创建过程的结束,就开始了代码执行阶段,在此时JavaScript会将变量对象(VO)转换成活动对象(AO)。在未进入到执行阶段之前,变量对象中的属性都不能访问,但是进入执行阶段后,由于变量对象被转换成了活动对象,里面的属性就可以被访问了,随后开始执行代码。因此在第二节的例子上,其实输出的都是活动对象的属性(但变量对象与活动对象中包含的属性与值都相同,所以姑且认为是变量对象)

  再总结一下,其实变量对象与活动对象都是同一个对象,只是它们处于不同的执行上下文生命周期。

四、全局变量对象

  以浏览器为例,全局变量对象为window对象。除此之外,全局变量对象的生命周期与执行上下文一致,所以如果浏览器窗口如果不关闭的话,全局变量对象将会一直存在。

JavaScript学习系列之执行上下文与变量对象篇的更多相关文章

  1. 深入学习JS执行--创建执行上下文(变量对象,作用域链,this)

    一.介绍 本篇继上一篇深入理解js执行--单线程的JS,这次我们来深入了解js执行过程中的执行上下文. 本篇涉及到的名词:预执行,执行上下文,变量对象,活动对象,作用域链,this等 二.预执行 在上 ...

  2. 再看javascript执行上下文、变量对象

    突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文.变量对象.作用域.this等语言细节.内容短小而精悍,文风直白而严谨,读完有酣畅淋漓 ...

  3. 1--面试总结-js深入理解,对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This

    参考一手资料:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/中文翻译版本:https://zhuanlan.zhihu.com/p ...

  4. JS进阶之---执行上下文,变量对象,变量提升

    一.结构顺序大体介绍 JavaScript代码的整个执行过程,分为两个阶段,代码编译阶段与代码执行阶段. 编译阶段由编译器完成,将代码翻译成可执行代码,这个阶段作用域规则会确定. 执行阶段由引擎完成, ...

  5. JavaScript 执行环境(执行上下文) 变量对象 作用域链 上下文 块级作用域 私有变量和特权方法

    总结自<高程三>第四章  理解Javascript_12_执行模型浅析   JS的执行环境与作用域  javascript高级程序第三版学习笔记[执行环境.作用域] 在javascript ...

  6. JavaScript学习系列博客_30_JavaScript Date 日期对象

    Date - 日期的对象,在JS中通过Date对象来表示一个时间 - 创建一个当前的时间对象 var d = new Date(); - 创建一个指定的时间对象 var d = new Date(&q ...

  7. JavaScript学习系列博客_13_JavaScript中的对象(Object)简介

    对象 对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性.除了那5种基本数据类型,就是对象. 分类:1.内建对象- 由ES标准中定义的对象,在任何的ES的实现中都可以使用- 比如:Ma ...

  8. 深入理解JavaScript系列(12):变量对象(Variable Object)

    介绍 JavaScript编程的时候总避免不了声明函数和变量,以成功构建我们的系统,但是解释器是如何并且在什么地方去查找这些函数和变量呢?我们引用这些对象的时候究竟发生了什么? 原始发布:Dmitry ...

  9. 透过一道面试题来探探JavaScript中执行上下文和变量对象的底

    在做面试题之前,我们先搞清楚两个概念 执行上下文(execution context) 变量对象(variable object) 执行上下文 我们都知道JavaScript的作用域一共分三种 全局作 ...

随机推荐

  1. 自建git服务器搭建使用记录

    git在push的时候出现insufficient permission for adding an object错误 //解决方法,在git库的目录下 //明明一开始创建user的时候有执行这个命令 ...

  2. nginx proxy_buffer_size 解决后端服务传输数据过多,其实是header过大的问题

    nginx proxy_buffer_size 解决后端服务传输数据过多,其实是header过大的问题 这三个参数已设置就搞定了额 proxy_buffer_size 64k; proxy_buffe ...

  3. wxpython学习资源

    http://www.cnblogs.com/dyx1024/archive/2012/07/15/2592202.html wxPython:布局管理器sizer介绍 ogs.com/dyx1024 ...

  4. UVA 10471 Gift Exchanging

    题意:就5种盒子,给出每个盒子个数,盒子总数,每个人选择这个盒子的概率.求这个人选择哪个盒子取得第一个朋友的概率最大,最大多少 dp[N][sta]表示当前第N个人面临状态sta(选择盒子的状态可以用 ...

  5. 搭建Spring框架,实现添加数据到数据库

    原创链接:http://www.cnblogs.com/yanqin/p/5284400.html (允许转载,但请注明原创链接) 1.在myeclipse中建立一个web项目 项目名 :spring ...

  6. Android之BInder分析

      MediaService的诞生: nt main(int argc, char** argv) { //FT,就这么简单?? //获得一个ProcessState实例 sp<ProcessS ...

  7. 【 Tomcat 】tomcat8.0 基本参数调优配置

    1.优化内核及TCP连接: fs.file-max = # 系统文件描述符总量 net.ipv4.ip_local_port_range = # 打开端口范围 net.ipv4.tcp_max_tw_ ...

  8. WPF中使用WPFMediaKit视频截图案例

    前台 代码: <Window x:Class="WpfAppWPFMediaKit.MainWindow" xmlns="http://schemas.micros ...

  9. H5中使用Web Storage来存储结构化数据

    在上一篇对Web Storage的介绍中,可以看到,使用Storage保存key—value对时,key.value只能是字符串,这对于简单的数据来说已经够了,但是如果需要保存更复杂的数据,比如保存类 ...

  10. UESTC 30.最短路-最短路(Floyd or Spfa(链式前向星存图))

    最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...