了解JavaScript中的变量范围

The scope is the execution context of a variable or function. It defines what data it has access to. This concept may seem pretty straightforward, but has some important subtleties.

作用域是变量或函数的执行上下文。 它定义了它有权访问的数据。 这个概念可能看起来很简单,但是有一些重要的微妙之处。

JavaScript has traditionally had two types of scope: global scope and local scope. The purpose of the scope is to provide access to all variables and functions that an execution context has access to.

传统上,JavaScript具有两种类型的范围:全局范围和局部范围。 范围的目的是提供对执行上下文可以访问的所有变量和函数的访问。

全球范围 (Global Scope)

When a variable is declared outside of any function it belongs to the global scope automatically and can be accessed from anywhere in the program, be it a function or any block. Also, if desired, in the browser we can create a global variable by declaring it as window.newVariable at any place in a program.

当变量在任何函数之外声明时,它将自动属于全局范围,并且可以从程序中的任何位置(无论是函数还是任何块)进行访问。 另外,如果需要,在浏览器中,我们可以通过在程序中的任何位置将其声明为window.newVariable来创建全局变量。

const nestAnimal = 'crocodilian';   // belongs to the Global scope

function getNestInfo(){
  window.eggs = 5;     // as well belongs to the Global scope
}

In fact, in the browser, variables in the global scope belong to the global window object.

实际上,在浏览器中,全局作用域中的变量属于全局window对象。

JavaScript is a garbage-collected language, it keeps available all variables while executing the program in the context and remove after. Let’s consider the lifecycle of the variable. The variable comes into existence during the execution of the function. The variable is used inside the function and then the function ends. At that point this variable is no longer needed, so its memory can be reclaimed and JavaScript remove this variable from the memory. But global variables remain in the memory for the all the time the application is running and clogs up it, which slows down the program, also it may cause unexpected name conflicts.

JavaScript是一种垃圾收集的语言,它在上下文中执行程序时保留所有变量可用,之后将其删除。 让我们考虑变量的生命周期。 该变量在函数执行期间就存在。 该变量在函数内部使用,然后函数结束。 那时不再需要此变量,因此可以回收其内存,JavaScript会从内存中删除此变量。 但是,全局变量在应用程序运行期间一直保留在内存中并阻塞它,这减慢了程序的速度,还可能导致意外的名称冲突。

That all means that, whenever possible, you should avoid to defining global variables. They are only truly needed in very specific cases, so be careful with this.

这一切都意味着,只要有可能,就应避免定义全局变量。 仅在非常特定的情况下才真正需要它们,因此请务必小心。

当地范围 (Local Scope)

ES6 introduced block-scoped variables using the const and let keywords. With these keywords, local scope is created and exists within the innermost block that surrounds it. It could be a function, for loop, while block, if block, etc. Such locally scoped variables can be only accessed from within that block.

ES6引入了使用constlet关键字的块范围变量。 使用这些关键字,将创建局部作用域,并将其存在于包围它的最里面的块中。 它可能是一个函数, for循环, while块, if块等。只能在该块内部访问此类局部范围的变量。

Each block has its own execution context which defines what data it has access to, as well as how it should behave. When code is executed in a context, a scope chain is created. It includes all declared variables and functions inside that block, then the data from the containing (parent) context, and so on. This pattern continue until the global context is reached.

每个块都有其自己的执行上下文,该上下文定义了它可以访问的数据以及其行为方式。 在上下文中执行代码时,将创建作用域链。 它包括该块内的所有已声明的变量和函数,然后是包含(父)上下文的数据,依此类推。 这种模式一直持续到达到全局为止。

Let’s have a look at an example:

让我们看一个例子:

let caymanMood = 'calm';

function changeMood(newMood){
  if (caymanMood === 'calm'){
    caymanMood = newMood;
  } else {
    caymanMood = 'calm';
  }
}

changeMood('happy');

The function changeMood has a scope chain with two objects in it: its own variable object (arguments object newMood) and the global context’s variable object caymanMood. The function has access to caymanMood because it’s part of its scope chain.

函数changeMood具有一个包含两个对象的作用域链:它自己的变量对象(参数对象newMood )和全局上下文的变量对象caymanMood 。 该函数可以访问caymanMood因为它是其作用域链的一部分。

范围链增强 (Scope Chain Augmentation)

It’s possible to augment the scope chain besides global and local execution contexts. We can do this in two ways.

除了全局和本地执行上下文外,还可以扩展作用域链。 我们可以通过两种方式做到这一点。

  • Point 1: A with statement

    第一点 :带有语句的A

  • Point 2: The catch block in a try...catch statement.

    第二点 : try...catch语句中的catch块。

function buildNest() {
  const assets = 'grass';
  with(reptilian){
    const building = ability + assets;
  }
  return building;
}

with creates a object that is added to the front of the scope chain, but the thing is when you read the code you can’t know for sure which object exactly will be modified. Will it be the global variable ability or the variable in this context reptilian.ability. So the correct execution of the program can’t be guaranteed. Use of the with statement is not recommended by the MDN web docs as it may be a source of confusing bugs and compatibility issues.

with创建一个对象,该对象被添加到作用域链的前端,但是问题是,当您阅读代码时,您无法确定确切地将修改哪个对象。 是全局变量ability还是此上下文中的reptilian.ability变量。 因此,不能保证程序的正确执行。 MDN Web文档不建议使用with语句,因为它可能导致令人困惑的错误和兼容性问题。

The catch statement creates a new variable object that contains a declaration for the thrown error object and this error object is added to the front of the scope chain.

catch语句创建一个新的变量对象,该对象包含对抛出的错误对象的声明,并且此错误对象被添加到作用域链的前面。

结语 (Wrapping Up)

With this, you should now have a slightly better understanding of how local and global scope works in JavaScript and how relying on the closest local context possible is a good idea for writing easily readable and maintainable code.

这样,您现在应该对本地和全局作用域如何在JavaScript中工作以及如何尽可能依赖最接近的本地上下文有了更好的理解,这是编写易于阅读和可维护的代码的好主意。

翻译自: https://www.digitalocean.com/community/tutorials/js-variable-scope

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值