在JavaScript的运行过程中,经常会遇到一些"奇怪"的行为,不理解为什么JavaScript会这么工作。

这时候可能就需要了解一下JavaScript执行过程中的相关内容了。

执行上下文

在JavaScript中有三种代码运行环境:

  • Global Code

    • JavaScript代码开始运行的默认环境
  • Function Code

    • 代码进入一个JavaScript函数
  • Eval Code

    • 使用eval()执行代码

为了表示不同的运行环境,JavaScript中有一个执行上下文(Execution context,EC)的概念。也就是说,当JavaScript代码执行的时候,会进入不同的执行上下文,这些执行上下文就构成了一个执行上下文栈(Execution context stack,ECS)

个人对于执行上下文的理解:

某个函数或全局代码的执行环境,该环境中包含执行代码需要的所有信息。

可以简单地理解为执行上下文是一个对象,对象中包含了执行代码的全局信息。

JS原理

原型链

执行上下文

事件循环

栈是什么

1、栈(Stack)是一种线性存储结构,它具有如下特点:

(1)栈中的数据元素遵守“先进后出"(First In Last Out)的原则,简称FILO结构。

(2)限定只能在栈顶进行插入和删除操作。

2、栈的相关概念:

(1)栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。

(2)压栈:栈的插入操作,叫做进栈,也称压栈、入栈。

(3)弹栈:栈的删除操作,也叫做出栈。

在此对栈不做过多解释,可以自行查阅资料学习。

变量对象

变量对象是与执行上下文相关的数据作用域。它是一个与上下文相关的特殊对象,其中存储了在上下文中定义的变量和函数声明。也就是说,一般VO中会包含以下信息:

  • 变量 (var, Variable Declaration);
  • 函数声明 (Function Declaration, FD);
  • 函数的形参

当JavaScript代码运行中,如果试图寻找一个变量的时候,就会首先查找VO。对于前面例子中的代码,Global Execution Context中的VO就可以表示如下:

对象引用

对象引用:如果变量是一个对象,实际上变量中存放的是对象的地址

对于这张图里面的对象引用可以有这两种说法:

user1持有用户对象的引用

user1指向用户对象

执行栈

上面说到了执行上下文栈,在这里说明一下执行上下文堆栈

Call Stack(执行上下文堆栈(执行栈)):组织管理程序运行过程中的执行上下文

var a=2;//函数说明function  bar() {var i=3;function foo(){var b=4;method();}foo();console.log("123");}function method(){console.log("abc");}//函数调用bar();

上述代码比较简单,这里说明一下函数运行的过程(自底向上看):

全局执行上下文  结束

Bar函数的执行上下文出栈

销毁Console.log函数的执行上下文

Console.log函数的执行上下文

Foo函数的执行上下文出栈

Method函数的执行上下文出栈

销毁Console.log函数的执行上下文

Console.log函数的执行上下文

Method函数的执行上下文

Foo函数的执行上下文

Bar函数的执行上下文

栈底:全局执行上下文

执行上下文的内容

  1. VO:variable object  变量对象,存放的是函数或全局代码执行过程中需要用到的局部变量
  2. Scope:作用域
  3. This
{vo:...,scope:...,this:....}

VO是一个对象,调用函数或执行全局代码时创建,创建一个VO,需要经过三步

  1. 确定函数形参的值(包括arguments对象)
function foo(a, b) {}foo(3, 4);

foo函数的执行上下文建立过程:

  1. 创建vo对象
  1. 确定形参值
function foo(a,b){vo:{a:3,b:4,arguments:{.......}
}
}

2.确定函数中所有的函数字面量声明

function foo(a, b) {
a();function a() {
console.log("hello");
}var i = 11;
var j = 22;
var bar = 100;
}
  1. 该函数必须是字面量声明,字面量声明提取到vo后,可以认为该声明失效
  2. 如果vo中出现同名属性,直接覆盖
  3. 确定函数中所有的变量声明(var变量声明),将其提取到上下文,值为undefined
  4. 如果当前vo出现同名属性,直接忽略
function foo(a,b){vo:{a:3,b:4,arguments:{.......},a:指向一个函数,i:undefined,j:undefined,bar:undefined
}
}

一个简单的小demo示例:

function test(a){
console.log(a); //fnfunction a(){
console.log("hello");
};
var a = function(){
console.log("haha");
}a(); //hahavar a = 34;console.log(a); //34
}test(5);

当上面的理解之后,对于为什么输出是这个结果,应该没有什么疑问。

面试真题

下面的文字解释都是以栈的角度入手,阅读时自底向上

Test1

在函数中寻找数据时,会先从vo中查找,

vo:{

foo:undefined  -->  10

}

输出结果:undefined   10

Test2

b的执行上下文入栈:

vo:{

a:指向函数 -->  10  函数结束

}

全局上下文:

vo:{

b:指向函数,

a:undefined  -->  1

输出:undefined 1

Test3

全局上下文:

vo{

foo:指向C函数 --> “A”  -->指向函数B

-->  B

}

最终输出:fn(C)  A  fn(B)  B  fn(B)  B

Test4

`

a的上下文

vo{

}

bar的上下文

vo{

a:3  --> 指向函数 ,

a1: undefined  -->  指向函数a,

a:1(全局里面找的1)

}

全局上下文:

vo:{

bar:指向函数bar,

foo:undefined  -->  1

}

最终输出结果:1

一篇文章让你理解面试难点:执行上下文(干货满满(附面试题))相关推荐

  1. 一篇文章助你理解Python3中字符串编码问题

    前几天给大家介绍了unicode编码和utf-8编码的理论知识,以及Python2中字符串编码问题,没来得及上车的小伙伴们可以戳这篇文章:浅谈unicode编码和utf-8编码的关系和一篇文章助你理解 ...

  2. (面经总结)一篇文章带你整理面试过程中关于Java 中多线程的创建方式的最全整理

    文章目录 一.Java线程的创建方式 二.继承Thread类 三.实现 Runnable 接口 四.通过ExecutorService和`Callable`实现有返回值的线程 五.基于线程池 六.面试 ...

  3. 深入理解Javascript之执行上下文(Execution Context)

    在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你就会明白javascript引擎内部在执行代码以前到底做了些什么,为什么某些函数 ...

  4. 金三银四,一篇文章解决简历和面试

    这个俗称"金三银四"的跳槽季,很多人都蠢蠢欲动,想要拿更高的薪资,想要去更大的平台-但我也要奉劝大家一句:三思而后行. 确实,春节过后,大家都在为开年做准备,跳槽也好,学习蓄力也罢 ...

  5. 一篇文章搞定前端面试

    本文旨在用最通俗的语言讲述最枯燥的基本知识 面试过前端的老铁都知道,对于前端,面试官喜欢一开始先问些HTML5新增元素啊特性啊,或者是js闭包啊原型啊,或者是css垂直水平居中怎么实现啊之类的基础问题 ...

  6. spring框架_一篇文章带你理解Spring框架

    虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧! 1.什么是S ...

  7. 一篇文章通透理解序列号实现原理

    1.序列号的本质 序列号等价于注册码,是软件发行商的一种维权手段,也就是正版软件的一个身份证.本质:防止盗版.按功能收费等. 目前,商用软件和共享软件绝大部份都是采用注册码授权的方式来保证软件本身不被 ...

  8. 原理 一篇文章通透理解序列号实现原理

    1.序列号的本质 序列号等价于注册码,是软件发行商的一种维权手段,也就是正版软件的一个身份证.本质:防止盗版.按功能收费等. 目前,商用软件和共享软件绝大部份都是采用注册码授权的方式来保证软件本身不被 ...

  9. 一篇文章带你理解爬虫究竟是什么?

    目录 前言 爬虫的应用场景 爬虫的技术选型 简单的爬虫 脑洞大开的爬虫解决思路 复杂的爬虫设计 音视频爬虫实战 一.先从几个方面来简单介绍我们音视频爬虫项目的体系 二.分步来讲下细节 三.遇到的问题和 ...

最新文章

  1. CodeGen结构循环回路
  2. GNS3的默认Telnet程序改成secureCRT
  3. 数据库和数据湖的关键概念性差异
  4. git 拉取远程分之到本地
  5. 问题:android学习内容破碎,我个人关于如何学习android的一些个人经历
  6. RxHttp 一条链发送请求之强大的Param类(三)
  7. 11月1日至11日 全国处理快件47.76亿件
  8. Ubuntu14.04 安装pip
  9. React + leaflet 地图瓦片 加载错乱 不能正常显示
  10. python将变量写入文件_python 如何把变量写入文件
  11. 计算机专业哪个专业不需要数学,计算机软件专业是不是需要数学很好啊
  12. python汇率的转换程序_用Python制作汇率转换小程序
  13. Day11如何衡量算法的时间复杂度和空间复杂度
  14. 计算机配置里面没有网络选项,win7网络共享中心里面的更改适配器设置里面没有无线网络连接...-win7适配器没有无线网络连接,win7网络适配器未...
  15. 手机微信和QQ接收到的文件路径
  16. CDD文件——CANdelaStudio
  17. 吃货联盟订餐系统项目
  18. matlab素描算法实现
  19. 博弈论第一章 完全信息静态博弈
  20. Spring注解讲解

热门文章

  1. 奇点汽车黄浴:SLAM的动态地图和语义问题
  2. ECCV18|这篇论文开源的车牌识别系统打败了目前最先进的商业软件(附Github地址)...
  3. 三相滤波器怎么接线_数字滤波器设计的一般套路
  4. 无意间发现BAT大佬总结的一份目标检测、卷积神经网络和OpenCV学习资料(教程/PPT/代码)...
  5. Kaggle—So Easy!百行代码实现排名Top 5%的图像分类比赛
  6. 非局部均值(Nonlocal-Mean)
  7. community 计算模块度_燃气模块炉使用信息采集表
  8. aspen plus大小_Aspen入门篇2—Aspen Plus 使用介绍
  9. 牛顿插值实验报告C语言,牛顿插值C语言.doc
  10. Docker-compose 常用命令