暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

图解 JavaScript 作用域链

前端新世界 2022-02-16
226
喜欢就关注我们吧


本文翻译自:
https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd

这次我们讲讲 JS 的作用域链。本文建立在大家已经了解执行上下文的基础上。

请看以下代码:

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
函数,作用域链看起来像这样:

作用域链基本上是一条对象的“引用链”,对象包含对在该执行上下文中可引用的值(和其他作用域)的引用。作用域链是在创建执行上下文时创建的,这意味着它是在运行时创建的!

但是,在本文中,就不讨论活动对象和执行上下文了,我们只关注作用域!在以下示例中,执行上下文中的键/值对表示作用域链对变量的引用。

全局执行上下文的作用域链引用了3个变量:值为Lydia
name
变量,值为21
age
变量,以及值为San Francisco
city
变量。在本地上下文中,引用了2个变量:值是Sarah
name
变量,值为22
age
变量。

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

本地作用域链中有对name
age
的引用!name
有值Sarah
age
有值22
。那么现在,当尝试访问city
时会发生什么呢?

为了找到city的值,引擎沿着作用域链往下走。基本上,引擎不会轻易放弃:它会尽全力去查看是否可以在本地范围所引用的外部作用域中(在本例中就是全局对象)找到变量city
的值。

在全局上下文中,我们用值San Francisco
声明了变量city
,因此有了对变量city
的引用。既然我们有了变量的值,那么函数getPersonInfo
就可以返回字符串Sarah is 22 and lives in San Francisco

我们可以沿着作用域链往下走,但不能沿着作用域链往上走。看到这里,可能你就觉得困惑了,这里的往上走和往下走是什么意思呢?那我再说明一下:你可以进入外部作用域,但不能进入更内部的作用域。用一种可视化的方式描述的话有点像瀑布:

甚至更进一步:

让我们以这段代码为例。

跟之前的几乎一模一样,但是有一个很大的区别在于:我们现在只在getPersonInfo
函数中声明了city
,而没有在全局作用域中声明。我们没有调用getPersonInfo
函数,因此也没有创建本地上下文。同样的,我们试着在全局作用域内访问name
age
city
的值。

抛出了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
  }
}

将作用域可视化:

可以看到有一个全局作用域,一个函数作用域和两个块作用域。由于变量的作用域局限在大括号内,因此我们能够声明变量message
两次。

快速回顾:

  • 作用域链可以视为对可在当前上下文中访问的值的引用链。
  • 作用域还可以重用在作用域链下游定义的变量,因为只能沿着作用域链向下进行,而不能向上。

作用域(链)就是这样!关于这方面其实还有很多值得说一说的内容,学海无涯嘛。感谢阅读。

(文本完,感谢阅读)

每日分享前端插件干货,欢迎关注!

点赞和在看就是最大的支持❤️

文章转载自前端新世界,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论