声明

本系列文章内容全部梳理自以下几个来源:

作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。

PS:梳理的内容以《JavaScript权威指南》这本书中的内容为主,因此接下去跟 JavaScript 语法相关的系列文章基本只介绍 ES5 标准规范的内容、ES6 等这系列梳理完再单独来讲讲。

正文-执行上下文EC和变量对象VO

EC:Execution Context,中文翻译执行上下文,也有翻译成执行环境的。

VO:Variable object,中文翻译变量对象。

这两个概念很重要,涉及到作用域以及作用域链的原理。

执行上下文 EC

先说说Android中的上下文:

  • Android

Android 中也有上下文:Context,四大组件都是上下文,还有一个全局的 Application上下文。在 Android 中基本是以四大组件为界限,每创建一个四大组件,都会产生一个上下文,比如每个 Activity 都是独立的上下文。

在 Android 中,上下文 Context 的作用大体上用于标识各种资源的所属,要加载一张图片、创建一个 View、弹一个 Dialog 等等,你需要告诉系统,这些是谁发出的指令,要挂载到哪个上下文,这些资源依赖于上下文的生命周期。

所以才会出现,有时弹 Dialog 或者更新某个 View 时抛异常说 Context 已销毁,因为它需要挂载的上下文已经销毁了,那么就没有上下文来统筹管理这些资源了,自然会抛异常。

  • JavaScript

在 JavaScript 中,上下文是指执行上下文,通俗点理解,代码执行的上下文,所以也有翻译成执行环境,可以通俗的把它理解成一个对象,对象名 EC,表示代码的执行上下文。

既然理解成一个对象,那么就有它创建的时机,在 JavaScript 中,每当要执行不同类型的代码时,就会创建一个执行上下文 EC。

而代码的类型分三种:

  • 全局代码
  • 函数代码
  • eval()执行的代码

最后一种不讨论,全局代码就是指写在函数外的代码,在前端里,当 HTML 加载一个 js 文件时,全局代码就会被执行,那么在全局代码执行前就会先创建一个全局的执行上下文 EC,之后每调用一次函数,要执行函数内的代码时,会再创建一个函数执行上下文 EC。

也就是说,不讨论 eval 的话,那么在 JavaScript 有两种执行上下文,一种是全局执行上下文,一种是函数执行上下文。

而每次创建一个执行上下文时,都会将其放入一个栈结构,这个栈就称为执行上下文栈(ECS),也有翻译成执行环境栈。

所以执行 js 文件代码期间,这个栈底一直是全局执行上下文,直到 js 文件代码执行结束。全局代码执行过程中,每调用一次函数,新创建一个函数执行上下文,就放入栈内。

因此,栈顶就表示当前执行的代码,如果栈顶是全局执行上下文,表示正在执行全局代码;如果栈顶是函数执行上下文,表示正在执行函数内的代码。当函数执行结束时,这个函数执行上下文就从栈中移出。

那么执行上下文(EC)有什么用呢?

用途可多了,跟 Android 不一样,Android 里由于是各种资源的组合使用,但在 JavaScript 中更多的是嵌套函数的变量使用。所以,用途之一就是保存各个变量。

将 EC 理解成一个对象的话,它有两个属性,一个是变量对象(VO),另一个是作用域链(Scope Chain)。对于全局执行上下文,当 HTML 加载一个 js 文件时,就会创建一个全局 EC,此时会创建它的两个属性:变量对象和作用域链。之后,每调用一次函数,创建这次函数执行的上下文,函数内部的变量的使用就依赖于这个函数执行上下文中的变量对象和作用域链。

也就是说,内部函数之所以可以使用外部函数内的变量,之所以可以使用全局变量,都是依赖于当前这个内部函数的执行上下文。

而且,变量之所以会提前声明也是因为执行上下文的因素。这些当讲解了执行上下文 EC 的创建过程就清楚了。

变量对象 VO

变量对象只是一个抽象的概念,可以通俗的理解成保存当前上下文所有变量的对象。

在不同的执行上下文中,它有不同的具体表现。

在全局执行上下文中,变量对象 VO 的具体表现就是全局对象,因为所有的全局变量其实都是全局对象的属性,而变量对象 VO 的作用是要保存当前上下文中的所有变量,所以此时的变量对象 VO 实际上是指向的全局对象。

尤其在前端中,全局对象就是 window,所以全局执行上下文的变量对象 VO = window。

在函数执行上下文中,因为变量对象 VO 是要保存当前上下文中所有的变量,一个函数内的变量包括:形参变量、局部变量、自身函数对象引用变量、arguments、this。

针对函数执行上下文,为了保存这些变量,特意创建了一个对象,称它为活动对象 AO,函数内所需的变量就都保存在 AO 中,所以在函数执行上下文中,变量对象 VO 的具体表现也就是 AO。

小结:变量对象 VO 是一个抽象概念,用于保存当前执行上下文中所有的变量。所以在全局执行上下文中,因为全局对象已经保存着当前上下文所有的变量,所以 VO 在这里的具体实现就是全局对象。在函数执行上下文中,由于要保存函数形参、局部变量、自身函数对象引用变量、arguments、this,所以新创建了一个叫活动对象 AO 来保存,此时 VO 的具体实现就是 AO。

作用域链

每次函数调用时,都会创建一个函数执行上下文 EC,但其中的变量对象 VO 只保存着当前上下文中的变量而已,那么函数内如果需要使用到外部函数的变量,甚至是使用全局的变量时,此时就需要依赖于执行上下文的另一个属性:作用域链。

作用域链本质上,其实是将有嵌套层次关系的执行上下文的 VO 拼接起来。

所以大部分场景作用域链只有两个节点:当前函数执行上下文的 VO –> 全局执行上下文的 VO。所以函数内才可以根据作用域链访问全局内的变量。

当出现函数内再嵌套函数时,此时作用域链就会比较长:

内层函数执行上下文的 VO –> 外层函数执行上下文的 VO –> 全局执行上下文 VO。

至于作用域链是如何将有嵌套层次的执行上下文的 VO 拼接起来,需要借助函数对象的内部属性 [[Scope]],[[]]表示执行引擎为对象创建的内部属性,我们访问不了,也操作不了。具体原理在作用域链一节中讲解。


大家好,我是 dasu,欢迎关注我的公众号(dasuAndroidTv),公众号中有我的联系方式,欢迎有事没事来唠嗑一下,如果你觉得本篇内容有帮助到你,可以转载但记得要关注,要标明原文哦,谢谢支持~

前端入门16-JavaScript进阶之EC和VO的更多相关文章

  1. 前端基础之JavaScript进阶

    一.流程控制 if - else var a = 10; if (a >5){ console.log("yes"); }else { console.log("n ...

  2. 前端入门18-JavaScript进阶之作用域链

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  3. 前端入门17-JavaScript进阶之作用域

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  4. 4、JavaScript进阶篇①——基础语法

    一.认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面,但这还不够,它只是静态页面 ...

  5. 结合个人经历总结的前端入门方法 (转自https://github.com/qiu-deqing/FE-learning)

    结合个人经历总结的前端入门方法 (https://github.com/qiu-deqing/FE-learning),里面有很详细的介绍. 之前一直想学习前端的,都不知道怎么下手都一年了啥也没学到, ...

  6. JavaScript进阶(一)

     OK接下来,我们再次梳理一遍js并且提高一个等级. 众所周知,web前端开发者需要了解html和css,会只用html和css创建一个漂亮的页 面,但是这肯定是不够的,因为它只是一个静态的页面,我们 ...

  7. 2019年Web前端入门的自学路线

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文.本文内容不定期更新. 我前几天写过一篇文章:<裸辞两个月,海投一个月 ...

  8. JavaScript进阶 - 第1章 系好安全带,准备启航

    第1章 系好安全带,准备启航 1-1让你认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂 ...

  9. JavaScript进阶之高阶函数篇

    JavaScript进阶之高阶函数篇 简介:欢迎大家来到woo爷说前端:今天给你们带来的是JavaScript进阶的知识,接下来的系列都是围绕着JavaScript进阶进行阐述:首先我们第一篇讲的是高 ...

随机推荐

  1. [Swift]LeetCode654. 最大二叉树 | Maximum Binary Tree

    Given an integer array with no duplicates. A maximum tree building on this array is defined as follo ...

  2. [Swift]LeetCode801. 使序列递增的最小交换次数 | Minimum Swaps To Make Sequences Increasing

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  3. [Swift]LeetCode938. 二叉搜索树的范围和 | Range Sum of BST

    Given the root node of a binary search tree, return the sum of values of all nodes with value betwee ...

  4. pytorch学习:准备自己的图片数据

    图片数据一般有两种情况: 1.所有图片放在一个文件夹内,另外有一个txt文件显示标签. 2.不同类别的图片放在不同的文件夹内,文件夹就是图片的类别. 针对这两种不同的情况,数据集的准备也不相同,第一种 ...

  5. C语言中你可能不熟悉的头文件(stdlib.h)

    C语言中你可能不熟悉的头文件<cstdlib>(stdlib.h) C Standard General Utilities Library (header) C标准通用工具库(头文件) ...

  6. WebSocket刨根问底(二)

    上篇文章[WebSocket刨根问底(一)]中我们对WebSocket的一些基本理论进行了介绍,但是并没有过多的涉及到一些实战的内容,今天我希望能够用几个简单的案例来向小伙伴们展示下WebSocket ...

  7. Chapter 5 Blood Type——31

    I stood carefully, and I was still fine. He held the door for me, his smile polite but his eyes mock ...

  8. ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段

      ServletRequest 基本概念 JavaWeb中的 "Request"对象  实际为   HttpServletRequest  或者  ServletRequest, ...

  9. spring学习(五) ———— 整合web项目(SSM)

    一.SSM框架整合 1.1.整合思路 从底层整合起,也就是先整合mybatis与spring,然后在编写springmvc. 1.2.开发需求 查询商品列表(从数据库中查询) 1.3.创建web工程 ...

  10. 什么是平衡二叉树(AVL)

    前言 Wiki:在计算机科学中,AVL树是最早被发明的自平衡二叉查找树.在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都 ...