作用域链的形成

在 JS 中每个函数都有自己的执行环境,而每个执行环境都有一个与之对应的变量对象。例如:

var a = 2
function fn () {
var a = 1
console.log(a)
}
fn() // 输出 1

你就可以将 fn 当做函数 fn 执行环境对应的一个变量对象,这个变量对象我们通过代码是无法访问到的,但是 JS

引擎在解析代码时会用到它。

思考为什么上面函数中的 fn 运行后输出 1,可能大家都知道,但是为什么会输出 1 呢,用上面的变量对象来理解就可以得出答案。实际上:

console.log(a)
// 等价于
console.log(fn.a)

这个 fn 就是函数 fn 对应的变量对象,我们通过代码没有办法得到它,但是 JS 引擎可以,并且利用它找了变量 a。

现在再来思考下面这一种情况:

var a = 3
function fn1() {
var a = 2
function fn2() {
console.log(a)
}
fn2()
}
fn1() // 输出 2

为什么输出 2 而不是 3 呢?

这就引出了作用域链,函数 fn2 对应的变量对象时是 fn2,函数 fn1 对应的变量对象是 fn1,全局执行环境对应的变量对象是 window 对象。当代码中的变量 a 在 fn2 中找不到时就不会去它的父环境 fn1 对应的变量对象 fn1 中去查找,发现有 a 变量就使用它。

实际上这个查找的过程就是沿着作用域链查找的过程。

当一个函数被执行时,就会创建一条由变量对象(函数执行时也叫活动对象)组成的作用域链,作用域链的前端就是当前代码执行所在环境对应的变量对象(即 fn2),下一个变量对象来自父环境对应的变量对象(即 fn1),一直到全局执行环境的变量对象 window。

因此,上面代码中的作用域链就是 fn1 -> fn2 -> window,查找标识符的顺序就是顺着作用域链从最前端开始依次向后查找,在某个变量对象中找到后就停止往后查找。

延长作用域链

既然我们知道作用域链的前端就是当前运行环境所在的变量对象,那么能不能人为地改变作用域链前端的变量对象呢?

答案是肯定的。

1)利用 try-catch 语句块中的 catch

catch 语句块中会创建一个新的变量对象,并且处于作用域链的最前端,其中包含的是被抛出的错误对象的声明。

2)with 语句

对于 with 语句来说会将指定的对象添加到作用域链的最前端。

浅析 JS 中的作用域链的更多相关文章

  1. 谈JS中的作用域链与原型链(1)

    学习前端也有一段时间了,觉得自己可以与大家分享一些我当初遇到疑惑的东西,希望能给对此问题有疑惑的朋友带来一点帮助. 先来普及一下JS的概念(不要嫌我啰嗦,可能一些朋友开始学习JS是跟着视频和写好的代码 ...

  2. JS中的作用域链

    在js中数据的声明方式有两种: 1.用var声明,例如:var num = 10: 2.直接声明,例如:num = 10: 两种声明方式在某些情况下是有区别的: var data = 10; func ...

  3. 第十八篇 js高级知识---作用域链

    一直有想法去写写js方面的东西,我个人是最喜欢js这门语言,喜欢的他的自由和强大,虽然作为脚本语言有很多限制的地方,但也不失为一个好的语言,尤其是在H5出现之后.下面开始说说js的方面的东西,由于自己 ...

  4. JS闭包、作用域链、垃圾回收、内存泄露相关知识小结

    补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...

  5. JS详细图解作用域链与闭包

    JS详细图解作用域链与闭包 攻克闭包难题 初学JavaScript的时候,我在学习闭包上,走了很多弯路.而这次重新回过头来对基础知识进行梳理,要讲清楚闭包,也是一个非常大的挑战. 闭包有多重要?如果你 ...

  6. JS中的作用域及闭包

    1.JS中的作用域 在 es6 出现之前JS中只有全局作用域和函数作用域,没有块级作用域,即 JS 在函数体内有自己的作用域,但是如果不是在函数体的话就全部都是全局作用域.比如在 if.for 等有 ...

  7. 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz

    浅析JS中的模块规范(CommonJS,AMD,CMD)   如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已.     ...

  8. 聊一下JS中的作用域scope和闭包closure

    聊一下JS中的作用域scope和闭包closure scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久 ...

  9. JS中的作用域以及全局变量的问题

    一. JS中的作用域 1.全局变量:函数外声明的变量,称为全部变量 局部变量:函数内部使用var声明的变量,称为局部变量在JS中,只有函数作用域,没有块级作用域!!!也就是说,if/for等有{}的结 ...

随机推荐

  1. Module Error (/index.js): error: 'HelloWorld' is defined but never used (no-unused-vars) at src\views\A.vue:9:8:

    原因:

  2. Pytest系列(11)- 失败重跑插件pytest-rerunfailures详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 环境前提 以下先决条件才能使用py ...

  3. Linux网络安全篇,认识防火墙(二),Netfilter

    一.概述 因为iptables软件利用的是数据包的过滤的机制.所以它会分析数据包的报头数据.根据报头数据与定义的规则来决定该数据是否可以放行.若数据包内容与规则内容相同则放行,否则继续与下一条规则进行 ...

  4. json === dict

    import requests import json ''' json.loads(json_str) json字符串转换成字典 json.dumps(dict) 字典转换成json字符串 ''' ...

  5. spark下载安装,运行examples(spark一)

    1.官方网址 http://spark.apache.org/ image.png 2.点击下载 下载最新版本目前是(2.4.3)此spark预设为hadoop2.7或者更高版本,我前面安装的是had ...

  6. Exchange 2016 OWA登陆异常

    今天,收到脚本的告警信息,有一台Exchange服务器OWA无法登陆! 手动进行了一下测试,发现确实存在问题,报错信息如下: 检查了一下该台服务器的日志,找到了如下信息 1.访问OWA的请求在HTTP ...

  7. java中JVM虚拟机内存模型详细说明

    java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03|  分类: JAVA |  标签:java  jvm  堆内存  虚拟机  |举报|字号 订阅     JVM的内部结构 ...

  8. CentOS7安装JAVA环境

    安装JAVA环境我常用的有两种形式 1.下载tar包安装 2.下载rpm包直接安装 本篇内容就写这两种形式的安装方法: JAVA程序的下载地址:https://www.oracle.com/java/ ...

  9. 深度解密 Go 语言之 sync.Pool

    最近在工作中碰到了 GC 的问题:项目中大量重复地创建许多对象,造成 GC 的工作量巨大,CPU 频繁掉底.准备使用 sync.Pool 来缓存对象,减轻 GC 的消耗.为了用起来更顺畅,我特地研究了 ...

  10. BUG 测试计划

       性能追求 目前状况 测试标准 APP平稳运行,无crush现象   快速下拉翻页时,崩溃退出     要求多人使用,均流畅无异常退出方可               页面的放大缩小不会造成页面显 ...