了解JavaScript中的变量范围

news/2024/7/4 2:58:51

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


http://www.niftyadmin.cn/n/3649733.html

相关文章

[j2me]二级菜单界面演练[四]

Opera Mini的菜单也是最下方绘制的矩形条,然后drawString上菜单命令,我也要这么做,毕竟这么做简单些。若要做到类似于ucweb那种几乎接近于Windows任务栏/工具栏的那种效果,还尚需时日。今日花费点时间调整到这样吧,把左…

[j2me]二级菜单界面演练[三][0215Update]

今日又花费了点时间,调整界面上各种按键之下的效果,比如:上下左右方向键的作用;点击一次“选择”左软键就是展开主菜单,再点击一次“选择”左软键的作用就是消隐主菜单;等等诸如此类的效果,和Wi…

如何安装svelte_Svelte 3入门

如何安装svelte介绍 (Introduction) When building applications with JavaScript, high performance and penetrability will always be at the crux of the decisions made by software developers. Svelte is a high-performance component framework for imperative code. …

如何使用信号量持续集成和交付将Node.js应用程序构建和部署到DigitalOcean Kubernetes

The author selected the Open Internet / Free Speech fund to receive a donation as part of the Write for DOnations program. 作者选择了“ 开放式互联网/言论自由”基金来接受捐赠,这是“ 为捐赠写信”计划的一部分。 介绍 (Introduction) Kubernetes allow…

[j2me]二级菜单界面演练[二]

全赖朋友指点迷津,终于调试出来些许效果。实际上调整这种Opera Mini风格的二级菜单效果,颇为费时费力,也颇为折磨人的锐气。我只能按照以前对付bloglines手机伴侣的制作手法,每日花费一点时间调试,但也并不投入过多的精…

Meme Engine话题(三):从噪音中寻找信号

从噪音中寻找信号 现在的Rss Reader们(如Bloglines)都做得很好,他们简化了我们的生活,但是当RSS已经或即将成为过量信息时,我们都会烦恼如何从噪音中找到信号。herock在《Attention.xml初探》也提到:“Attention.XML试图解决的&am…

用Technorati Mini来跟踪blog世界

是一个小窗口,他会根据你的搜索关键词每隔1分钟就自动搜索1次,这样你一直让他保持着,你就可以像一个疯子一样持续不断地跟踪blog世界中每时每秒发表的和这个关键词有关的文章了。一个不错的主意,莫非keso是凭借这个小工具不断地自…

oauth2 github_如何使用oauth2_proxy保护GitHub登录后的私有Kubernetes服务

oauth2 github介绍 (Introduction) Kubernetes ingresses make it easy to expose web services to the internet. When it comes to private services, however, you will likely want to limit who can access them. oauth2_proxy can serve as a barrier between the public…