⚡️⛓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())
我们正在调用该函数,该函数返回一个字符串,其中包含、和变量getPersonInfo
的值: 。但是,该函数不包含名为🤨 的变量?它是如何知道 的值的?name
age
city
Sarah is 22 and lives in San Francisco
getPersonInfo
city
city
首先,为不同的上下文设置内存空间。我们有一个默认的全局上下文(window
在浏览器中,global
在 Node 中),以及一个用于调用函数的本地上下文。每个上下文都有一个作用域链。getPersonInfo
对于getPersonInfo
函数来说,作用域链看起来像这样(别担心,它现在还不需要有意义):
作用域链本质上是一个对象的“引用链”,其中包含对可在该执行上下文中引用的值(以及其他作用域)的引用。(⛓:“嘿,这些都是你可以在这个上下文中引用的值。”)作用域链在执行上下文创建时创建,也就是说它是在运行时创建的!
不过,我不会在这篇文章中泛泛地讨论激活对象或执行上下文,我们只关注作用域!在下面的例子中,执行上下文中的键/值对代表了作用域链对变量的引用。
全局执行上下文的作用域链引用了 3 个变量:name
值为 的变量Lydia
、age
值为 的变量21
和city
值为 的变量San Francisco
。在局部上下文中,我们引用了 2 个变量:name
值为 的变量Sarah
和age
值为 的变量22
。
当我们尝试访问getPersonInfo
函数中的变量时,引擎首先检查本地作用域链。
局部作用域链中有一个对 的引用name
!age
它name
的值为Sarah
,age
的值为22
。但是现在,当它尝试访问 时会发生什么city
?
为了找到city
引擎所需的值,它会“沿着作用域链向下走”。这基本上意味着引擎不会轻易放弃:它会努力寻找是否能city
在外部作用域中找到局部作用域所引用的变量的值,在本例中是全局对象。
在全局上下文中,我们声明了city
值为 的变量San Francisco
,因此引用了该变量city
。现在我们有了变量的值,函数getPersonInfo
就可以返回字符串了Sarah is 22 and lives in San Francisco
🎉
我们可以沿着作用域链向下移动,但不能沿着作用域链向上移动。(好吧,这可能有点让人困惑,因为有些人会说“向上”而不是“向下” ,所以我就重新表述一下:你可以进入外层作用域,但不能进入更内层……(更内层……?)的作用域。我喜欢把它想象成一种瀑布:
甚至更深层次:
我们以这段代码为例。
它几乎相同,但是有一个很大的区别:我们现在只city
在函数中声明,而不是在全局范围内。我们没有调用该函数,因此也没有创建本地上下文。然而,我们尝试在全局上下文中访问、和的值。getPersonInfo
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
两次,因为变量的作用域在花括号内。
快速回顾一下:
- 您可以将“作用域链”视为我们可以在当前上下文中访问的值的引用链。
- 作用域还可以重新使用在作用域链中进一步定义的变量名,因为它只能沿着作用域链向下,而不能向上。
关于作用域(链)就讲到这里!关于这个还有很多要说的,等我有空的时候再补充。如果你遇到任何问题,欢迎随时提问,我很乐意提供帮助!💕
文章来源:https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd