儿子:爸,我有个愿望,当有一天我疲惫回家时,你打电话告诉我,家里有百亿家产等我继承,之前装穷都是为了锻炼我。爸:别着急,爸爸也在等你爷爷的电话呢。- 随时继承百亿家业的Scope(Chain)

周生生技术:作用域(链)概览图

请注意上面这张图,作用域(链)的那些事,将在这个图上缓缓展开。

是时候聊聊作用域链了。我假设大家对执行上下文有一些基本认识:后面我会专门写一篇文章来介绍它。


上代码:

const name = "Lydia"

const age = 21

const city = "San Francisco"

function getPersonInfo() {

const name = "Sarah"

const age = 22

return `${name} is ${age} and lives in ${city}`

}

console.log(getPersonInfo())

`getPersonInfo`函数返回一个字符串,字符串中包含了`name`, `age` 和 `city`这三个变量的值: `Sarah is 22 and lives in San Francisco`。 但是在`getPersonInfo`函数中,并没有一个叫`city`的变量,它是从哪儿取到`city`的值的?

首先,不同的上下文都有各自的内存空间。

默认我们有个全局上下文(在浏览器里面是window,在Node中是global),还有`getPersonInfo`函数的本地上下文。每个上下文都会有一个自己的作用域链

对于`getPersonInfo`函数,作用域链看起来是下面这个样子(别担心,目前它可能还不是很好理解):

1、作用域链

作用域链大体就是一个引用链,它指向执行上下文引用的对象(包含别的作用域),它说,嗨,这里就是所有你能够在这个上下文中使用的变量。作用域链在执行上下文创建的时候被创建,这也意味着,它是在运行时被创建的。

但是,我不会在这一章中讨论活动对象或者执行上下文,让我们把火力集中在作用域上!在接下来的例子中,执行上下文中的键值对代表了作用域链中指向变量的引用。

2、执行上下文的键值对

全局执行上下文的作用域链有一个引用指向三个变量:值为`Lydia`的`name`,值为`21`的`age`和值为`San Francisco`的`city`。

本地上下文中,我们有一个引用指向两个变量:值为`Sarah`的`name`和值为`22`的`age`。

当我们在`getPersonInfo`函数中访问变量时,引擎会首先检查本地作用域链。

3、函数中访问变量

本地作用域链包含指向`name`和`age`的引用!`name` 的值是`Sarah` ,`age` 的值是`22`. 但是,当我们访问`city`时会发生什么呢?

为了找到`city`的值,引擎“沿着作用域链往下找”。这说明引擎不是那么容易放弃的:本地作用域引用了一个变量,因为不是在本地作用域中声明的,引擎会竭尽全力在外部作用域中去寻找。在这里指的是全局对象

4、函数中访问外部变量

在全局上下文中,我们声明了变量 `city`并赋值`San Francisco`,因此在全局上下文中有变量`city`的引用。现在我们有值了,函数`getPersonInfo`返回了字符串`Sarah is 22 and lives in San Francisco`。


我们可以顺着作用域链往下走,但是不能沿着作用域链往上走(好吧这里可能会有点迷惑,因为有些人会把下说成上,所以我重新描述一下:你可以走到外部作用域中,但是不能走进内部作用域)。

我喜欢把这个视觉化为一个瀑布模型:

5、作用域链的瀑布模型

或者更深一些:

6、作用域链的深层瀑布模型


接下来看如下例子:

7、作用域链的作用范围

大体看起来似乎和上面的差不多,但是这里有个很大的区别:我们只在`getPersonInfo`函数中声明变量`city`,而没有在全局作用域中声明。我们没有调用`getPersonInfo`函数,所以也没有本地上下文被创建。所以看起来我们打算在全局上下文中访问变量`name`, `age` 和 `city`。

8、引用错误

结果,它抛出了错误`ReferenceError`!它在全局作用域中找不到一个名叫`city`的变量,并且这里也没有更外部的作用域可以继续寻找,也表示没法沿着作用域链往上找。

通过这种方式,你可以用作用域来保护你的变量和重用变量名字。


除了全局作用域本地作用域,还有一种块作用域。通过`let` 和 `const`声明的变量,他们被限制在大括号的范围中。

const age = 21

function checkAge() {

if (age < 21) {

const message = "You cannot drink!"

return message

} else {

const message = "You can drink!"

return message

}

}

你可以把作用域视觉化如下:

9、块作用域的视觉化

我们有一个全局作用域,一个函数作用域,两个块作用域。我们可以声明变量message两次,因为它被限制在大括号里头。


敲黑板划重点:

  • 作用域链是引用链,指向在当前上下文中引用的变量的值。
  • 作用域让重用低层作用域的变量名变成可能,因为它只能是顺着作用域往下,而不是往上走。

这就是作用域(链)!它还有很多故事,等我有时间再继续。如果有疑问请随时提问,我喜欢助人为乐!

译者:

原文作者是个可爱的小女孩,所以文章中有很多的感叹号,经过男性强行修饰后可能有所减少。

翻译来源:https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd

javascript感叹号1_「翻译」JavaScript的可视化学习之三:作用域(链)相关推荐

  1. jsp循环输出表格_「翻译」JS可视化学习之七:Promise、事件循环和异步2

    喜欢排队吧,它能保护你的时间和精力 - 排队纪律维护员Event Loop Promise和事件循环概览图 请注意上面这张图,Promise和事件循环的那些事,将在这个图上缓缓展开. 微任务和(宏)任 ...

  2. 变量、中文-「译」javascript 的 12 个怪癖(quirks)-by小雨

    在写这篇文章之前,xxx已经写过了几篇关于改变量.中文-主题的文章,想要懂得的朋友可以去翻一下之前的文章 原文:12 JavaScript quirks 译文:「译」javascript 的 12 个 ...

  3. 「翻译」Unity中的AssetBundle详解(一)

    AssetBundles AssetBundle是一个存档文件,其中包含平台在运行时加载的特定资产(模型,纹理,预制,音频剪辑,甚至整个场景).AssetBundles可以表示彼此之间的依赖关系;例如 ...

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

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

  5. 「译」javascript 中的 delete

    在这篇文章中作者从<JavaScript面向对象编程指南>一书中关于 delete 的错误讲起,详细讲述了关于 delete 操作的实现, 局限以及在不同浏览器和插件(这里指 firebu ...

  6. 「完结」你对深度学习模型的理解是否足够深刻,这12篇文章了解下

    2020-05-28 18:07:49 文/编辑 | 言有三 好的模型结构是深度学习成功的关键因素之一,不仅是非常重要的学术研究方向,在工业界实践中也是模型是否能上线的关键.对各类底层深度学习模型设计 ...

  7. 「杂谈」如何系统性地学习生成对抗网络GAN

    文/编辑 | 言有三 作为被誉为"下一代深度学习技术",同时已经在工业界能够真正成熟稳定应用的GAN,有三AI公众号很早之前就开始关注相关内容,从理论到实践都做出了一些总结,并且在 ...

  8. 「译」JavaScript 的 MVC 模式

    原文:Model-View-Controller (MVC) with JavaScript 作者:Alex@Net 译文:JavaScript 的 MVC 模式 译者:justjavac 本文介绍了 ...

  9. 「知识点」JavaScript 中11个有趣的事实

    1. NaN 是一个 number 类型 NaN是一个number类型. 而且,NaN不等于它自己. 实际上NaN不等于任何东西,验证一个变量是否是NaN可以使用isNaN()方法来判断. > ...

最新文章

  1. usaco Calf Flac(O(n)时间求回文串长度)
  2. 世界地板大会姚红鹏的三问
  3. 深入分析 Javascript 单线程
  4. python函数手册 stata_Stata连享会-Python量化
  5. 常用的好用的window工具
  6. 自学提高:JVM点滴
  7. mycat是什么_MyCat
  8. python如何用requests传送json格式数据
  9. Java从入门到进阶书单推荐|必收藏
  10. 实验八 集成稳压器
  11. python项目实战:天眼查询你所需的公司信息
  12. vscode连接模拟器运行flutter项目
  13. 基于汇编实现的欢乐QQ堂小游戏 附完整代码
  14. 数据库实验4---数据完整性
  15. tcpdump抓syn,ack,fin,rst包
  16. 电子计算机按数字错乱,PC数字键盘错乱怎么修复?笔记本键盘按键错乱如何恢复?...
  17. 如何用JS实现“划词高亮标记”的在线笔记功能?
  18. 老人与海好词100英文带翻译_老人与海 英文版经典句子
  19. 案例分析:运营菜鸟应该注意哪些细节?
  20. GDSOI2019退役记

热门文章

  1. 思想解读:TF-A(ATF)中栈指针和栈内存的设计思想解读
  2. Repo 命令参考资料
  3. linux kernel中的wait_for_completion和complete总结
  4. [toolchains]-ARM ToolChains介绍
  5. 使用docker-compose部署sentinel
  6. C语言获取数组越界,除以零等异常
  7. 结构体对齐,#pragma pack
  8. EasyRE 寒假逆向生涯(5/100)
  9. 2020-11-20(页帧)
  10. Pycharm解决中文字体大小不一致问题