本文主要介绍JS执行上下文相关的内容,理解了JavaScript的执行上下文才能更好地理解JavaScript语言本身以及该语言一些特性,如变量提升、作用域和闭包。

一、作用域

1.1 作用域

作用域是指程序中变量定义的区域,该位置决定了变量的生命周期。通俗地说,作用域就是变量与函数的可访问范围,作用域控制着变量和函数的可见性和生命周期。

JavaScript在设计之初并未想过这门语言会如此受欢迎,所以只是按照最简单的方式来设计,只保留全局作用域和函数作用域。

  • 全局作用域中对象和变量在任何地方都能访问,其生命周期同页面的生命周期。

  • 函数作用域是在函数内部定义的变量或函数,只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。

1.2 变量提升

JavaScript在执行前会先进行编译,编译阶段会将变量和函数存放在执行上下文的变量环境中,值设为undefined。编译完成进入执行阶段,使用变量时从变量环境中读取,在执行变量的赋值代码前,读取该变量时值均为默认值 undefined。

变量提升给初学者带来了很多疑惑,有如下问题:

  • 变量容易在不被察觉的情况下被覆盖掉

var myname = "JavaScript";function showName{ console.log(myname); // undefined if(0){ var myname = "Go" } console.log(myname);}showName;
  • 本应销毁的变量没有被销毁

function foo{ for (var i = 0; i < 7; i++) { } console.log(i); // for循环结束后i变量没有被销魂}foo;

1.3 块级作用域

为了解决变量提升等问题、打造JavaScript为企业级的开发语言,ES6引入了 let 和 const 关键字,从而使 JavaScript 也能像其他语言一样拥有了块级作用域。

我们已经知道 JavaScript 引擎是通过变量环境实现函数级作用域的,那么 ES6 又是如何在函数级作用域的基础之上,实现对块级作用域的支持呢?

我们来看个例子:

function foo { var a = 1; let b = 2; { let b = 3; var c = 4; let d = 5; console.log(a); console.log(b); } console.log(b); console.log(c); console.log(d)}foo;

当执行上面这段代码的时候,JavaScript 引擎会先对其进行编译并创建执行上下文,然后再按照顺序执行代码,现在我们引入了 let 关键字,let 关键字会创建块级作用域,那么 let 关键字是如何影响执行上下文的呢?

接下来我们就来一步步分析上面这段代码的执行流程。

第一步是编译并创建执行上下文,执行上下文如下图所示:

从上图可以看出:

  • 函数内部通过 var声明的变量,在编译阶段会被存放到变量环境中。

  • 通过 let声明的变量,在编译阶段会存放到词法环境中。

  • 在函数的作用域内部,通过 let 声明的变量并没有被存放到词法环境中。

第二步是执行代码,当执行到函数代码块里面时(第4行),当执行到代码块里面时,变量环境中 a 的值已经被设置成了 1,词法环境中 b 的值已经被设置成了 2,这时候函数的执行上下文就如下图所示:

从图中可以看出,当进入函数的作用域块时,作用域块中通过 let 声明的变量,会被存放在词法环境的一个单独的区域中,这个区域中的变量并不影响作用域块外面的变量,比如在作用域外面声明了变量 b,在该作用域块内部也声明了变量 b,当执行到作用域内部时,它们都是独立的存在。

其实,在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。需要注意下,我这里所讲的变量是指通过 let 或者 const 声明的变量。

再接下来,当执行到作用域块中的 console.log(a) 这行代码时,就需要在词法环境和变量环境中查找变量 a 的值了,具体查找方式是:沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给 JavaScript 引擎,如果没有查找到,那么继续在变量环境中查找。

当作用域块执行结束之后,其内部定义的变量就会从词法环境的栈顶弹出,最终执行上下文如下图所示:

总结一下,块级作用域就是通过词法环境的栈结构来实现的,而变量提升是通过变量环境来实现,通过这两者的结合,JavaScript 引擎也就同时支持了变量提升和块级作用域了。

以及其任何超类对此上下文都是未知的_浏览器原理系列 - JS执行上下文详解(一):作用域相关推荐

  1. 以及其任何超类对此上下文都是未知的_ECCV'20 |OCRNet化解语义分割上下文信息缺失难题...

    编者按:图像语义分割一直都是场景理解的一个核心问题.针对语义分割中如何构建上下文信息,微软亚洲研究院和中科院计算所的研究员们提出了一种新的物体上下文信息--在构建上下文信息时显式地增强了来自于同一类物 ...

  2. 小白都能懂的 玩转docker系列之 Docker网络详解(超详细)

    首先移掉之前所有的容器: [root@xiaoxiao tomcat]# docker rm $(docker ps -aq) fcfddcab1789 [root@xiaoxiao tomcat]# ...

  3. javascript系列之执行上下文

    写在前面:一 直想系统的总结一下学过的javascript知识,喜欢这门语言也热爱这门语言.未来想从事前端方面的工作,提前把自己的知识梳理一下.前面写了些 DOM的知识,略觉水平有限.没几个月就要开赴 ...

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

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

  5. 以及其任何超类对此上下文都是未知的_web前端入门到实战:Javascript 中的「上下文」你只需要看这一篇

    正文 上下文 是Javascript 中的一个比较重要的概念, 可能很多朋友对这个概念并不是很熟悉, 那换成「作用域」 和 「闭包」呢?是不是就很亲切了. 「作用域」和「闭包」 都是和「执行上下文」密 ...

  6. java都界面相对布局_浏览器的重排和重绘

    浏览器的高层结构 1.用户界面 - 包括地址栏.前进/后退按钮.书签菜单等. 2.浏览器引擎 - 在用户界面和呈现引擎之间传送指令. 3.渲染引擎 - 负责显示请求的内容. 4.网络 - 用于网络调用 ...

  7. 小白都能看懂的go语言包管理工具DEP详解

    简介 众所周知GO语言包管理工具百花齐放,前有godep.glide.govendor,后有dep. 今天我们来了解一下"dep",看看它是怎样实现包管理的. dep安装 二进制文 ...

  8. 稳扎稳打JS——执行上下文

    上下文环境的初始化在代码执行前完成 JS有三种作用域:全局作用域.函数作用域.eval作用域(不常用,不做介绍). 在JS代码执行前,首先会对这三种作用域进行上下文环境的准备工作,准备内容如下: 全局 ...

  9. 华为交换机默认vlan都是通的吗_华为设备二层交换技术——Hybrid接口详解

    Hybrid接口的特点 按照VLAN接口封装类型,华为交换机的接口主要有三种模式:Access.Trunk和Hybrid.其中Access.Trunk接口和Cisco技术并无差异,Hybrid接口是华 ...

最新文章

  1. 国内操作系统OS分析(上)
  2. 自动驾驶 | MINet:嵌入式平台上的实时Lidar点云数据分割算法,速度可达 20-80 FPS!...
  3. HDOJ2019 ( 数列有序! ) 【水题】
  4. Java数据结构和算法:字符串、数组和广义表
  5. ehcache springboot_Spring Boot应用缓存实践之:Ehcache加持
  6. SAP GUI和Windows注册表
  7. python 虚线_Python 包安装和管理工具 pip 19.2 发布
  8. lsof 列出谁在使用某个端口
  9. RS232通讯数据解析C#
  10. mysql使用join和不使用join_在SQL或MySQL中不使用JOIN关键字的联接有问题吗?
  11. 《算法分析》——布线问题
  12. IEEE1588 同步机制
  13. 硬盘功率测试软件,CPU功耗检测
  14. 推挽输出与开漏输出结构和原理详解
  15. yabailv 运放_压摆率——限制了运放的速度
  16. DirectX11 With Windows SDK--28 计算着色器:波浪(水波)
  17. 判断入射满射c语言编码,例4,判断下列函数是否是满射、单射、双射。.PDF
  18. matlab 定义一个cell,未定义与 'cell' 类型的输入参数相对应的函数 'min'。
  19. [转]关于寻路算法的一些思考
  20. 数据挖掘简介(摘自维基百科)

热门文章

  1. curl php 空,直接访问链接有数据,CURL GET 一片空白
  2. mysql三个字段最优索引_mysql 多列索引优化
  3. c++ vector 存放指针_STL-C++ vector部分
  4. mySql的case when用法
  5. oracle统计一个班男生女生,一条sql统计一个班级的男女人数
  6. tankwar java,TankWar 單機(JAVA版) 版本0.4~版本0.6 讓坦克動起來
  7. Linux USB 驱动开发(一)—— USB设备基础概念
  8. 使用libjpeg显示JPEG图像在framebuffer 测试(八)
  9. css 动态rem_【面试题】CSS知识点整理(附答案)
  10. 如何修改xd.properties文件中对象存储文件信息_对块存储、文件存储、对象存储的认识总结...