J

⚡️⛓JavaScript 可视化:作用域(链)NEAT 讨论

2025-05-28

⚡️⛓JavaScript 可视化:作用域(链)

整洁的

讨论

是时候了解作用域链了🕺🏼 在这篇文章中,我假设您了解执行上下文的基础知识:不过我很快也会写一篇关于它的文章😃


我们来看看下面的代码:



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())


Enter fullscreen mode Exit fullscreen mode

我们正在调用该函数,该函数返回一个字符串,其中包含变量getPersonInfo的值: 。但是,该函数不包含名为🤨 的变量?它是如何知道 的值的nameagecity
Sarah is 22 and lives in San FranciscogetPersonInfocitycity

首先,为不同的上下文设置内存空间。我们有一个默认的全局上下文window在浏览器中,global在 Node 中),以及一个用于调用函数本地上下文。每个上下文都有一个作用域链getPersonInfo

对于getPersonInfo函数来说,作用域链看起来像这样(别担心,它现在还不需要有意义):

替代文本

作用域链本质上是一个对象的“引用链”,其中包含对可在该执行上下文中引用的值(以及其他作用域)的引用。(⛓:“嘿,这些都是你可以在这个上下文中引用的值。”)作用域链在执行上下文创建时创建,也就是说它是在运行时创建的!

不过,我不会在这篇文章中泛泛地讨论激活对象或执行上下文,我们只关注作用域!在下面的例子中,执行上下文中的键/值对代表了作用域链对变量的引用。

替代文本

全局执行上下文的作用域链引用了 3 个变量:name值为 的变量Lydiaage值为 的变量21city值为 的变量San Francisco。在局部上下文中,我们引用了 2 个变量:name值为 的变量Sarahage值为 的变量22

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

替代文本

局部作用域链中有一个对 的引用nameagename的值为Sarahage的值为22。但是现在,当它尝试访问 时会发生什么city

为了找到city引擎所需的值,它会“沿着作用域链向下走”。这基本上意味着引擎不会轻易放弃:它会努力寻找是否能city在外部作用域中找到局部作用域所引用的变量的值,在本例中是全局对象

替代文本

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


我们可以沿着作用域链向下移动,但不能沿着作用域链向上移动。(好吧,这可能有点让人困惑,因为有些人会说“向上”而不是“向下” ,所以我就重新表述一下:你可以进入外层作用域,但不能进入更内层……(更内层……?)的作用域。我喜欢把它想象成一种瀑布:

替代文本

甚至更深层次:

替代文本


我们以这段代码为例。

替代文本

它几乎相同,但是有一个很大的区别:我们现在city在函数中声明,而不是在全局范围内。我们没有调用该函数,因此也没有创建本地上下文。然而,我们尝试在全局上下文中访问的值。getPersonInfogetPersonInfonameagecity

替代文本

它抛出了一个ReferenceError!它无法找到对全局作用域中调用的变量的引用city,并且没有外部作用域可供查找,因此它无法沿作用域链向上查找。

这样,您可以使用范围来“保护”变量并重新使用变量名。


除了全局和局部作用域之外,还有块作用域。使用letconst关键字声明的变量的作用域为最近的花括号 ( {})。



const age = 21

function checkAge() {
  if (age < 21) {
    const message = "You cannot drink!"
    return message
  } else {
    const message = "You can drink!"
    return message
  }
} 


Enter fullscreen mode Exit fullscreen mode

您可以将范围可视化为:

替代文本

我们有一个全局作用域、一个函数作用域和两个块作用域。我们可以声明变量message两次,因为变量的作用域在花括号内。


快速回顾一下:

  • 您可以将“作用域链”视为我们可以在当前上下文中访问的值的引用链。
  • 作用域还可以重新使用在作用域链中进一步定义的变量名,因为它只能沿着作用域链向下,而不能向上

关于作用域(链)就讲到这里!关于这个还有很多要说的,等我有空的时候再补充。如果你遇到任何问题,欢迎随时提问,我很乐意提供帮助!💕

文章来源:https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd
PREV
RESTful API 简介
NEXT
8 个需要牢记的 SCSS 最佳实践