执行上下文

  • 可执行代码

    avaScript中可执行代码(executable code)分为三种:全局代码,函数代码和eval代码。 可执行代码与执行上下文的概念是相对的,在某些语义下,可执行代码与执行上下文是等价的。

  • 执行上下文

    执行上下文(Execution Context,EC),也称执行环境,每当控制器执行到可执行代码的时,就会进入到一个执行上下文。 执行上下文可以理解为可执行代码的"运行环境",分为三种:

      全局环境:当一段程序开始执行时,会首先进入全局执行文环境,浏览器中是window对象,只有没有关闭浏览器,一直存在。函数环境:每当函数被调用执行时,就会进入一个新的上下文环境。(函数递归调用也会进入)eval环境:eval函数调用的时候产生的执行上下文。
    复制代码

    执行上下文也可以抽象理解为一个对象,这个对象都有三个属性:

      变量对象(variable object)、作用域链(scope chain)、this指针(this value)。
    复制代码

    不同执行上下文变量对象略有不同:

      全局上下文中的变量对象就是全局对象,允许通过变量对象的属性名来间接访问。函数上下文中用活动对象来表示变量对象,通过函数的arguments属性初始化。
    复制代码

    执行上下文生命周期分为两个阶段:创建阶段和代码执行阶段

      创建阶段:创建变量对象,建立作用域链,确定this指向代码执行阶段:变量赋值,函数引用,执行其他代码
    复制代码
  • 执行上下文栈

JavaScript引擎通过执行上下文栈(Execution Context Stack)来管理执行上下文。

当一个执行上下文(caller)激活了另一个上下文(callee),这个caller就会暂停它自身的执行,将控制权交给callee,于是callee被压入栈顶,称为当前上下文。当这个callee的上下文结束之后被弹出,然后caller从暂停的地方继续执行。一个callee可以用返回(return)或抛出异常(exception)来结束自身的上下文。
复制代码

ECStack底部永远都是全局上下文(global EC),而顶部就是当前(激活的)执行上下文(active EC)。

    // demo1var scope = "global scope";function checkscope(){var scope = "local scope";function foo(){return scope;}return foo();}checkscope();// 1.首先向执行上下文栈中压入全局执上下文ECStack = [globalContext];// 2.调用checkscope(),checkscope执行上下文被压入ECStackECStack.push[checkscopeContext] = [checkscopeContext,globalContext];// 3.调用foo(),foo执行上下文被压入ECStackECStack.push[fooContext] = [fooContext,checkscopeContext,globalContext];// 4.foo()执行结束,foo执行上下文被弹出ECStackECStack.pop[fooContext] = [checkscopeContext,globalContext];// 5.checkscope()执行结束,checkscope执行上下文被弹出ECStackECStack.pop[checkscopeContext] = [globalContext];// demo2var scope = "global scope";function checkscope(){var scope = "local scope";function foo(){return scope;}return foo;}checkscope()();// 1.首先向执行上下文栈中压入全局执上下文ECStack = [globalContext];// 2.调用checkscope(),checkscope执行上下文被压入ECStackECStack.push[checkscopeContext] = [checkscopeContext,globalContext];// 3.checkscope()执行结束后返回foo函数体,checkscope执行上下文被弹出ECStackECStack.pop[checkscopeContext] = [globalContext];// 4.foo函数体被返回后调用执行,foo执行上下文被压入ECStackECStack.push[fooContext] = [fooContext,globalContext];// 5.foo()执行结束,foo执行上下文被弹出ECStackECStack.pop[fooContext] = [globalContext];
复制代码

变量对象

变量对象(variable object,VO)是与执行上下文相关的数据作用域,用于存储定义在上下文中的变量和函数声明。 函数表达式不包含在变量对象中。

    var num = 10; // 变量声明function fun() {} // 函数声明, FD(function bar() {}); // 函数表达式, FEconsole.log(this.num === num, // truewindow.fun === fun // true);console.log(bar); //  "bar" is not defined// globalContext.VO = {fun: <fun reference>, // 函数fun的引用地址num: undefined   // 变量num,赋值为undefined}
复制代码

在全局上下文中,变量对象就是全局对象(在浏览器中是window对象),允许通过全局对象的属性名来访问全局变量。 在函数执行上下文中,用活动对象(active object,AO)来表示变量对象,AO不能直接访问。 活动对象除了变量和函数声明,还存储了形参和arguments对象。 arguments对象是对形参的一个映射,但是值是通过索引来获取(类数组)。

    function foo(x, y) {var z = 30;function bar() {} // FD(function baz() {}); // FE}foo(10, 20);//fooContext.AO = {arguments: {0: 10,1: 20,length: 2},bar: <bar reference>,x: 10,y: 20,z: 30}
复制代码

在进入执行环境时,变量对象会进行如下初始化:

(1)arguments对象,对象中的值被赋予具体的实参值。
(2)函数的形参:创建一个属性,其属性名为形参名,其值为实参的值;对于没有传递的参数,其值为undefined。
(3)函数声明:创建一个属性,其属性名和值都是函数对象创建出来的,其值为指向某个函数对象的引用;如果该函数名的属性已存在,则该属性会被新的引用覆盖。
(4)变量声明:创建一个属性,其属性名即为变量名,其值为undefined。如果变量名与已声明的形参或函数名相同,则会直接跳过,原属性值不会被修改。变量只能使用var关键字声明,不使用var关键字的赋值语句仅仅是给全局对象创建了一个新属性,不是变量。
复制代码

总结:在进入执行上下文的时候(比如进入全局环境或者某个函数被调用),变量对象除了arguments、函数的声明以及参数被赋予了具体的属性值,其它的变量属性默认的都是undefined。在执行到函数内部的具体某个语句的时候,上面所述的值为undefined的变量,其值都会被赋予具体的值。

    function test() {var a = 1;function foo() {return 2;}var bar = function () {return 'hello';};}test();// test()调用时进入该函数执行上下文testContext = [VO: {}, // 创建变量对象Scope: {}, // 建立作用域链this:{} // 确定this指向]// 创建变量对象VO,里面的属性不能被访问AO = {arguments: {length: 0}, // 初始化Arguments对象foo: <foo reference>, // 函数foo的引用地址a: undefined   // 变量a,赋值为undefinedbar: undefined   // 变量bar,值为undefined}// 执行阶段AO = {arguments: {length: 0},foo: <foo reference>,a: 1   // 变量a,赋值该为1bar: <bar reference> // 匿名函数的引用地址赋值给bar}
复制代码

每进入到一个执行环境都会创建一个变量对象,这个对象中记录了在当前执行环境中可以访问到的变量和函数,它们以变量对象的属性形式存在。也就是说这个变量对象成为“作用域”这个抽象概念的实体。

参考资料:

《JavaScript 标准参考教程》

汤姆大叔-深入理解JavaScript系列

转载于:https://juejin.im/post/5a9e5b9ef265da239235dc9f

01-执行上下文与变量对象相关推荐

  1. 一、 函数调用栈,执行上下文及变量对象

    前言 为什么会有这篇文章? 在书籍或博客上,我们经常会看到「作用域链」.「闭包」.「变量提升」等概念,说明一个问题 -- 它们很重要. 但很多时候,对于这些概念,看的时候觉得自己已经明白了,可过不了多 ...

  2. JavaScript学习系列之执行上下文与变量对象篇

    一个热爱技术的菜鸟...用点滴的积累铸就明日的达人 正文 在上一篇文章中讲解了JavaScript内存模型,其中有提到执行上下文与变量对象的概念.对于JavaScript开发者来说,理解执行上下文与变 ...

  3. java函数ao活动对象_JavaScript中的执行上下文和变量对象

    执行上下文(Execution Context) JavaScript代码执行的过程,包括编译和执行两个阶段,编译就是通过词法分析,构建抽象抽象语法树,并编译成机器识别的指令,在JavaScript代 ...

  4. 串讲-解释篇:作用域,作用域链,执行环境,变量对象,活动对象,闭包

    这篇接:理论篇:作用域,作用域链,执行环境,变量对象,活动对象,闭包 看例子: function compare(value1, value2) {if (value1 < value2) {r ...

  5. 2.JS执行上下文和变量对象

    文章目录 执行上下文栈 函数上下文 变量对象 执行过程 进入执行上下文 代码执行 两个例子 1 2   JS 是单线程语言,因此执行顺序是顺序执行,不过 JS 引擎在执行 JS 代码的时候并不是逐行执 ...

  6. JavaScript——执行环境、变量对象、作用域链

    前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体.通过上网查资料,特来总结,以备回顾和修正. 目录: EC(执行环境或 ...

  7. JS深入--词法作用域、执行上下文与闭包

    文章目录 词法作用域 执行上下文与词法环境 闭包 闭包练习 作用域链 REF   个人博客文章同步地址 词法作用域   JS 使用的是词法作用域(或称为静态作用域),函数的作用域在定义的时候就决定了, ...

  8. JavaScript深入之变量对象

    JavaScript深入系列第四篇,具体讲解执行上下文中的变量对象与活动对象.全局上下文下的变量对象是什么?函数上下文下的活动对象是如何分析和执行的?还有两个思考题帮你加深印象,快来看看吧! 前言 在 ...

  9. 一起再看执行上下文/作用域链/原型链

    作为小白入坑的这段时间,这三个概念很早便深入我心,但是却总感觉模模糊糊不知道该怎么讲清楚其中的关系,甚至有时候还会混淆,正好今天拿出来复盘一下. 举三个栗子 执行上下文 简单直白的讲执行上下文就是一种 ...

最新文章

  1. muduo网络库学习(六)缓冲区Buffer及TcpConnection的读写操作
  2. 如何使用域组策略(AD GPO)分发软件安装以及卸载[1.31.2013更新]
  3. python大数据_python大数据
  4. java量_Java 2. 量与常量
  5. python语法(二)——截取字符串的方法详解
  6. 模板模式(Template Pattern)
  7. antdPro Nginx 打包部署
  8. 一、JDK下载安装、eclipse下载安装(带资源)
  9. 简易租赁合同(免费)
  10. Linux(Ubuntu)触摸屏校准
  11. 怎么做gif?一分钟帮你搞定gif制作
  12. 市场调研—全球及中国活化部分凝血活酶时间测试(APTT测试)行业研究及十四五规划分析报告
  13. 内外兼修:Oracle ACED熊军谈Oracle学习
  14. lisp画弯箭头_在CAD中直接用命令画箭头
  15. 幼儿抽象逻辑思维举例_熊孩子到底在想什么—幼儿思维干货速记!
  16. pta 哥尼斯堡的“七桥问题”
  17. HTML-table单行操作
  18. (转)DVD转换RMVB格式的方法
  19. 反射 Nio channel Buffer
  20. C# winform 简单五子棋 200行代码实现人机对战

热门文章

  1. [原]pomelo开发环境搭建
  2. 正则提取 html 里input 标记的value 值
  3. Ogre1.8.1 Basic Tutorial 6 - The Ogre Startup Sequence
  4. Oracle传统基本体系结构初步介绍(2)
  5. GMQ区块链生态系统平行链,未来将应用于众多产业
  6. 无限滑动的banner图,中间显示大图两边显示一部分,无限滚动
  7. Nginx+Tomcat负载均衡群集
  8. ubuntu16全程安装mysql5.7.15!
  9. TypeScript手册翻译系列4-模块
  10. mac OS X 10.9.2 gdb codesign