JavaScript深入之执行上下文栈

如果要问到 javascript 代码执行顺序的话,想必写过javascript的开发者都会有个直观的印象,那就是顺序执行,例如:

var foo = function(){
  console.log(‘foo1‘)
}
foo() // foo1

var foo function(){
   console.log(‘foo2‘)
}
foo() // foo2

然而去看这段代码:

function foo(){
  console.log(‘foo1‘);
}

foo() // foo2

function foo(){
  console.log(‘foo2‘)
}

foo() // foo2

打印的结果却是两个 foo2

刷过面试题的都知道这是因为javascript引擎并非一行一行的分析和执行程序,而是一段一段的分析执行。

当执行一段代码的时候,会进行一个“准备工作”,比如第一个例子中的变量提升,和第二个例子中的函数提升。

但是本文真正想让大家思考的是: 这个 “一段一段” 中的 “段” 究竟是怎么划分的呢?

到底 javascript 引擎遇到一段怎样的代码时才会做“准备工作”呢?

可执行代码

这就要说到 javascript 的可执行代码(executable code)的类型有哪些了?

其实很简单,就三种,全局代码,函数代码,eval代码。

举个例子,当执行到一个函数的时候,就会进行准备工作,这里的 “准备工作”, 让我们用个更专业一点的说法,就叫做 "执行上下文(execution context)"

执行上下文栈

接下来问题来了,我们写的函数很多,如何管理创建的那么多执行上下文呢?

所以 javascript 引擎创建了执行上下文栈(Execution context stack, ECS) 来管理执行上下文。

为了模拟执行上下文栈的行为,让我们定义执行上下文栈是一个数组:

ECStask = [];

试想当javascript开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack才会被清空,所以 ECStack 最底部永远有个 globalContext:

ECStack = [
  globalContext
]

现在javascript 遇到下面的这段代码了:

function fun3(){
  console.log(‘fun3‘)
}
function fun2(){
  fun3()
}
function fun1(){
  fun2()
}

fun1();

当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。知道了这样的工作原理,让我们来看看如何处理上面这段代码:

// 伪代码

// fun1()
ECStack.push(<fun1> functionContext);

// fun1中竟然调用了fun2,还要创建fun2的执行上下文
ECStack.push(<fun2> functionContext);

// fun2中调用了 fun3
ECStack.push(<fun3> functionContext);

// fun3执行完毕
ECStack.pop();

// fun2执行完毕
ECStack.pop();

// fun1执行完毕
ECStack.pop();

// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext

参考文章:https://github.com/mqyqingfeng/Blog/issues/2

原文地址:https://www.cnblogs.com/zhouyangla/p/8375770.html

时间: 2024-10-13 15:48:53

JavaScript深入之执行上下文栈的相关文章

深入理解javascript原型和闭包(11)——执行上下文栈

摘自:http://www.cnblogs.com/wangfupeng1988/p/3989357.html:作者:王福朋: 继续上文的内容. 执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境.当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境.处于活动状态的执行上下文环境只有一个. 其实这是一个压栈出栈的过程--执行上下文栈.如下图: 可根据以下代码来详细介绍上下文栈的压栈.出栈过程. 如上代码. 在执行代码之前,首先将创建全局上

javascript系列之执行上下文

原文:javascript系列之执行上下文 写在前面:一 直想系统的总结一下学过的javascript知识,喜欢这门语言也热爱这门语言.未来想从事前端方面的工作,提前把自己的知识梳理一下.前面写了些 DOM的知识,略觉水平有限.没几个月就要开赴找工作的前线,奈何自己还是个菜鸟,具体写的时候还没有一个完整的思路.多番考虑之后,决定还是翻译外国的 经典系列文章,总结提升的同时,英语水平也可以上一个台阶,双管齐下,相信对以后肯定有好处.当然这个系列的文章已经有好多人翻译过了,水平都挺高(我翻 译过之后

JavaScript学习--Item19 执行上下文(execution context)

在这篇文章里,我将深入研究JavaScript中最基本的部分--执行上下文(execution context).读完本文后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如何决定的. 1.EC-执行环境或者执行上下文 每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文(好高大上的概念啊). javascript中,EC分为三种: 全局级别的代码 –– 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境. 函数级别的代码

js基础梳理-究竟什么是执行上下文栈(执行栈),执行上下文(可执行代码)?

日常在群里讨论一些概念性的问题,比如变量提升,作用域和闭包相关问题的时候,经常会听一些大佬们给别人解释的时候说执行上下文,调用上下文巴拉巴拉,总有点似懂非懂,不明觉厉的感觉.今天,就对这两个概念梳理一下,加深对js基础核心的理解. 1. 执行上下文(execution context)与可执行代码(execution code) 1.1 首先说一下,可执行代码的类型有哪些: 全局代码:例如加载外部的js文件或者本地标签内的代码.全局代码不包括 function 体内的代码 函数代码:functi

278 执行上下文、执行上下文栈:变量提升与函数提升,执行上下文,执行上下文栈,全局执行上下文,函数执行上下文,练习题

变量提升与函数提升 变量提升: 在变量定义语句之前, 就可以访问到这个变量(undefined) 函数提升: 在函数定义语句之前, 就执行该函数 先有变量提升, 再有函数提升 变量声明提升.函数声明提升 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>01_变量声明提升.函数声明提升</title> &l

JS 作用域 作用域链 执行上下文 执行上下文栈

当我想要整理作用域这块的时候,看各种博客,发现看的我都有点迷糊了,尴尬啊.. 下面说的都以下面这个例子解释 全局对象: 变量a1,函数fun1 一:作用域 在函数fun1声明时,会在scope中存放能访问到的所有资源,他能访问到的也就是全局对象. 二:作用域链 在函数执行时,会生成执行环境excution context,执行环境中存放活动对象.作用域链scope chain.this,作用域链中存放 活动对象.变量对象.全局对象 二:执行上下文 执行上下文也叫做执行环境,执行环境定义了变量或函

javascript作用域、执行上下文、原型和原型链

一.作用域js中作用域是指可访问变量,对象,函数的集合,也就是调用它们能生效的代码区块.在js中没有块级作用域,只有全局作用域和函数作用域 1.全局,函数作用域 var a = 10 function f1(){ var b = c = 20; console.log(a); ? ? //10 console.log(c); ? ? //20 function f2() { console.log(b); //20 }f2(); } f1(); console.log(a); ? ? //10

JavaScript探究之执行上下文

JavaScript代码的执行过程分为两个阶段: 代码编译阶段,由编译器完成,将代码翻译成可执行代码 代码执行阶段,由引擎完成,主要任务是执行可执行代码 可执行代码分为三种: 全局代码 函数代码 eval代码 一.执行上下文(EC) 当代码运行到一个环境时,就会进行“准备工作”,这里的“准备工作”称为“执行上下文”,也叫执行上下文环境,执行环境. 执行上下文的组成: 变量对象 作用域链 this指针 二.执行上下文的生命周期 创建 生成变量对象,建立作用域链,确定this指向 执行 变量赋值,函

JavaScript进阶之执行上下文和执行栈

js引擎的执行过程 执行上下文和执行栈属于js引擎的执行过程的预编译阶段. 执行上下文(Execution Context) 执行上下文是当前 JavaScript 代码被解析和执行时所在环境的抽象概念.可以理解为当执行代码时做的准备工作. 执行上下文按照运行环境被分成三类: 全局执行上下文(JS代码加载完毕后,进入代码预编译即进入全局环境) 函数环境执行上下文(函数调用执行时,进入该函数环境,不同的函数则函数环境不同) eval执行上下文(不建议使用,会有安全,性能等问题) 对于每个执行上下文