
Time for the scope chain 🕺🏼 In this post I assume you know the basics of execution contexts: I’ll soon write a post on that too though 😃
作用域 🕺🏼 在本文中,我假设您了解执行上下文的基础: 尽管如此,我也将很快就此发表一篇文章 😃
Let’s take a look at the following code:
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());
We’re invoking the getPersonInfo function, which returns a string containing the values of the name, age and city variables:Sarah is 22 and lives in San Francisco. But, the getPersonInfo function doesn’t contain a variable named city 🤨? How did it know the value of city?
我们调用
getPersonInfo函数,该函数返回一个包含name,age和city变量的值:Sarah is 22 and lives in San Francisco.但是,该getPersonInfo函数不包含名为city🤨 的变量.它怎么知道city的值?
First, memory space is set up for the different contexts. We have the default global context (window in a browser, global in Node), and a local context for the getPersonInfo function which has been invoked. Each context also has a scope chain.
首先,为不同的上下文设置存储空间.我们有默认的 全局上下文 (在浏览器中是
window,在 node 是global),以及局部上下文为getPersonInfo已调用的功能.每个上下文也都有一个 作用域链.
For the getPersonInfo function, the scope chain looks something like this (don’t worry, it doesn’t have to make sense just yet):
对于
getPersonInfo函数,作用域链看起来像这样(不用担心,它现在还没有必要):

The scope chain is basically a “chain of references” to objects that contain references to values (and other scopes) that are referencable in that execution context. (⛓: “Hey, these are all the values you can reference from within this context”.) The scope chain gets created when the execution context is created, meaning it’s created at runtime!
作用域链基本上是对对象的”引用链”,这些对象包含对在该执行上下文中可引用的值(和其他作用域)的引用.(⛓: “嘿,这些都是您可以在此上下文中引用的所有值”.)作用域链是在创建执行上下文时创建的,这意味着它是在运行时创建的!
However, I won’t talk about the activation object or the execution contexts in general in this post, let’s just focus on scope! In the following examples, the key/value pairs in the execution contexts represent the references that the scope chain has to the variables.
但是,在本文中,我一般不会讨论激活对象或执行上下文,我们只关注作用域!在以下示例中,执行上下文中的键/值对表示作用域链对变量的引用.

The scope chain of the global execution context has a reference to 3 variables: name with the value Lydia, age with the value 21, and city with the value San Francisco. In the local context, we have a reference to 2 variables: name with the value Sarah, and age with the value 22.
全局执行上下文的作用域链引用了 3 个变量:
name带有值Lydia,age带有值21,city带有值San Francisco.在本地上下文中,我们引用了 2 个变量:name带有值Sarah和age使用值22.
When we try to access the variables in the getPersonInfo function, the engine first checks the local scope chain.
当我们尝试访问该
getPersonInfo函数中的变量时,引擎首先检查本地作用域链.

The local scope chain has a reference to name and age! name has the value of Sarah and age has the value of 22. But now, what happens when it tries to access city?
本地作用域链引用了
name和age!name的值为Sarah,age的值为22.但是现在,当它尝试访问city时会发生什么?
In order to find the value for city the engine “goes down the scope chain”. This basically just means that the engine doesn’t give up that easily: it works hard for you to see if it can find a value for the variable city in the outer scope that the local scope has a reference to, the global object in this case.
为了找到
city的值, 引擎”必须深入作用域链中”.这基本上只是意味着引擎不会轻易放弃: 它会努力使您查看是否可以city在局部作用域引用的外部作用域(在这种情况下为全局对象)中找到变量的值.

In the global context, we declared the variable city with the value of San Francisco, thus has a reference to the variable city. Now that we have a value for the variable, the function getPersonInfo can return the string Sarah is 22 and lives in San Francisco 🎉
在全局上下文中,我们
city使用的值声明了变量San Francisco,从而引用了该变量city.现在我们有了变量的值,该函数getPersonInfo可以返回字符串Sarah is 22 and lives in San Francisco🎉
We can go down the scope chain, but we can’t go up the scope chain. (Okay this may be confusing because some people say up instead of down, so I’ll just rephrase: You can go to outer scopes, but not to more inner… (innerer..?) scopes. I like to visualize this as a sort of waterfall:
您可以使用外部作用域,但不能进入更内部…(内部…)作用域.我想形象地看到这一点.作为一种瀑布:

Or even deeper:

Let’s take this code as an example.

It’s almost the same, however there’s one big difference: we only declared city in the getPersonInfo function now, and not in the global scope. We didn’t invoke the getPersonInfo function, so no local context is created either. Yet, we try to access the values of name, age and city in the global context.
几乎一样,但是有一个很大的不同: 我们现在 在
getPersonInfo函数中仅声明city,而没有在全局作用域中声明.我们没有调用该getPersonInfo函数,因此也没有创建本地上下文.然而,我们试图在全局作用域内访问name,age并city的值.

It throws a ReferenceError! It couldn’t find a reference to a variable called city in the global scope, and there were no outer scopes to look for, and it cannot go up the scope chain.
它抛出
ReferenceError!它在全局作用域内,找不到一个叫做city变量的引用,并没有到外部作用域寻找,它不能上朔作用域链.
This way, you can use scope as a way to “protect” your variables and re-use variable names.
这样,您可以将作用域用作”保护”变量并重新使用变量名的方法.
Besides global and local scopes, there is also a block scope. Variables declared with the let or const keyword are scoped to the nearest curly brackets ({``}).
除了全局和局部作用域之外,还有一个块作用域.用
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;
}
}
You can visualize the scopes as:
您可以将作用域可视化为:

We have a global scope, a function scope, and two block scopes. We were able to declare the variable message twice, since the variables were scoped to the curly brackets.
我们有一个全局作用域,一个函数作用域和两个块作用域.
message由于变量的作用域用大括号括起来,因此我们能够两次声明该变量.
To quickly recap:
- You can see “scope chain” as a chain of references to values that we can access in the current context.
- Scopes also make it possible to re-use variable names that were defined further down the scope chain, since it can only go down the scope chain, not up.
- 您可以将”作用域链”视为对我们可以在当前上下文中访问的值的引用链.
- 作用域还可以重用在作用域链下游定义的变量名称,因为它只能在作用域链中向下移动,而不能向上.
That was it for scope (chains)! There’s tons more to say about this so I may add extra info when I have some free time. Feel free to ask questions if you’re struggling with anything, I love to help! 💕
作用域(链)就是这样!关于这一点还有更多的话要说,所以当我有空闲时间时,我可能会添加更多信息.如果您遇到任何困难,请随时提出问题,我很乐意提供帮助!💕