发布于 2026-01-06 1 阅读
0

范围与结束

范围与结束

如果每个死人都变成鬼魂,那就会有超过1000亿个鬼魂缠着我们所有人。虽然有点吓人,但也挺酷的。

——尼尔·德格拉斯·泰森

在今天的文章中,我们将介绍一些 JavaScript基础知识,帮助我们理解作用域和闭包。无论未来参与维护框架的项目,还是仅仅使用原生 JavaScript,它们在当今的互联网世界中都无处不在。我们将把内容分成几个部分,以便深入理解不同类型的作用域。由于信息量太大,一篇文章无法全部涵盖,所以为了节省时间,今天我们只讨论作用域和闭包。之后,我们将深入探讨数组方法、原型和继承以及类等强大的编程范式。让我们开始吧!

内容

  1. 全球范围
  2. 功能范围
  3. 块范围
  4. 提升(声明和初始化)
  5. 关闭
  6. 结论

引言

JavaScript 中的作用域和闭包是如何运作的?作用域定义了我们当前可以访问哪些变量以及在哪里可以访问这些变量。了解这些基本概念非常重要,因为它们在代码中几乎无处不在,而且面试官也会问到新开发者,以确保他们理解词法环境的工作原理。

全球范围

作用域有不同的层级,可以帮助我们编写更好的代码。作用域是一个很大的概念,如果我们深入研究的话,会发现它非常复杂。但我们的目标是理解函数和方法如何相互协作以获得特定输出的基本概念。我假设大家都熟悉全局作用域。全局作用域允许我们在代码的任何位置访问任何已创建的变量。当你深入查看更多代码时,这一点应该会更加清晰。

在下面的示例中,我们在函数外部声明了一个变量,在函数内部声明了一个变量。`var1`存储了一个字符串('hello'),而`var2``guesting` 函数内部也存储了一个字符串('world')。我们使用`console.log()`输出这两个变量,得到了两个不同的输出。第一个输出是 'hello',因为我们是在全局作用域中调用 `console.log () `,这里的所有内容都位于函数外部,可以在代码的任何位置访问。第二个 ` console.log() ` 输出是'undefined',因为我们试图访问存储在函数内部的变量。下一步我们将深入探讨其背后的原因。

#Javascript Scope and Closure

# Global Scope
# declare variable
const var1 = 'hello';

# Function Scope
function greeting(){
const var2 = 'world';
};
console.log(var1); #output = 'hello'
console.log(var2); #output = 'undefined'

进化是生命科学乃至整个生物学的基本思想。

比尔·奈

功能范围

如何在函数内部访问变量?函数作用域允许我们在函数内部声明变量,这些变量仅存在于函数内部,不会在代码的其他地方被访问。这些变量是该函数自身的私有变量。这种方法的唯一缺点是,我们无法外部访问函数内部的这些变量,但函数可以访问其作用域之外的变量。

#Javascript Scope and Closure

# Global Scope
# declare variable
const var1 = 'hello';

# Function Scope
function greeting(){
const var2 = 'world';
console.log(var1); # output 'hello';
console.log(var2); # output 'hello';
};

# Invoke function
greeting();

块范围

当我们使用if/else语句和for 循环时,通常会用到代码块级作用域。用letconst声明的变量只能在语句或循环内部访问(例如for循环中的i)。将语句组合成代码块(其他语言称之为复合语句)是 JavaScript 中的常见做法。代码块级作用域是另一个话题,它涉及如何使用var、letconst来声明变量,以及它们各自的作用域。MDN文档中有一篇很棒的关于代码块级作用域的维基文章。

吊装

通常情况下,我们在声明变量时倾向于像这样在同一行中声明。

var greeting = 'hello world';

通常情况下,我们不必按照 JavaScript 的规则这样做,也可以分别声明它们,也能得到相同的结果,这是可以接受的。

# declare variable
var greeting;

# store string
greeting = 'hello world';

编译器会在底层负责声明所有变量,然后再初始化它们,最后运行脚本的其余部分。但当文件中的代码行数很多时,这可能会变得很棘手。根据以下信息,如果我们尝试运行下面的代码,会发生什么?输出结果是什么?

# use variable
console.log(myVar);
# declare and initialize variable
aar myVar = 'variable';

答案是未定义。为什么?因为编译器运行时,首先会将变量声明为 undefined,然后再运行脚本。编译器会这样解释这段代码:

var myVar; # undefined
console.log(myVar); # output myVar
myVar = 'variable'

另一个例子。

sayHello();

function sayHello(){
console.log('hello')
}

上述代码的输出结果为“hello” 。为什么呢?这意味着函数可以在声明或初始化之前使用 这仅适用于已声明的函数,不适用于函数表达式。使用`var``function`关键字声明的函数会被提升,因此可以在脚本中的任何位置使用。如果尚未初始化,这些函数将返回`undefined`
。 关键字`let``const`不会被提升,这意味着它们不能在任何地方使用,否则会抛出 ` ReferenceError`。所以,最后,你不能在给`let``const`变量赋值之前就使用它们。

关闭

什么是闭包?闭包如何帮助我们理解 JavaScript?当一个函数被声明时,它同时也会创建一个新的作用域。在该函数的作用域内声明的变量会被包含在一个词法/私有作用域中,该作用域只属于该函数。函数还会向外查找上下文。如果某些变量没有在函数的作用域内定义,函数会向外查找寻找在外部作用域中被引用的变量。这就是闭包的本质。

结论

我希望读完本文后,您能够学会如何编写代码,并理解每一行代码的运行机制。理解代码的完整工作原理至关重要,这不仅能帮助您成为更优秀的开发者,还能帮助您更高效地使用各种工具。

这些文章主要是为了个人提升编程和写作能力而写的,旨在提高我的编程技能。如果您有任何反馈或建议,欢迎随时提出,这对我和其他读者都很有帮助。感谢您耐心读到这里!

文章来源:https://dev.to/cleveroscar/scope-closure-27fh