3️ ⚡️⛓JavaScript Visualized: Scope (Chain)


3️ ⚡️⛓JavaScript Visualized: Scope (Chain)

Cover image for ⚡️⛓JavaScript Visualized: Scope (Chain)

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 , agecity 变量的值: 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 函数,作用域链看起来像这样(不用担心,它现在还没有必要):

Alt Text

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.

但是,在本文中,我一般不会讨论激活对象或执行上下文,我们只关注作用域!在以下示例中,执行上下文中的键/值对表示作用域链对变量的引用.

Alt Text

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 带有值 Sarahage 使用值 22.

When we try to access the variables in the getPersonInfo function, the engine first checks the local scope chain.

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

Alt Text

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?

本地作用域链引用了 nameagename 的值为 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 在局部作用域引用的外部作用域(在这种情况下为全局对象)中找到变量的值.

Alt Text

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:

您可以使用外部作用域,但不能进入更内部…(内部…)作用域.我想形象地看到这一点.作为一种瀑布:

Alt Text

Or even deeper:

Alt Text


Let’s take this code as an example.

Alt Text

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 , agecity 的值.

Alt Text

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 ({``}).

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

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:

您可以将作用域可视化为:

Alt Text

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! 💕

作用域(链)就是这样!关于这一点还有更多的话要说,所以当我有空闲时间时,我可能会添加更多信息.如果您遇到任何困难,请随时提出问题,我很乐意提供帮助!💕


文章作者: Lydia Hallie
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lydia Hallie !
  目录