【发布时间】:2021-02-10 12:50:02
【问题描述】:
我想确保掌握变量作用域的概念。理想情况下,我想要一个表单的定义:
- x 是标识符 i 的 范围,以防万一 x ...
或形式:
- 标识符i的范围等同于...
虽然我是编程新手,但我已经阅读了一些关于变量作用域的 general material 和一些关于 JavaScript 中变量作用域的材料(包括 this)。但是,我似乎找不到一个精确的、描述性的定义。我试图想出自己的想法,但我注意到它并不总是适合其他人的说法。
最好能说明我目前的理解。让我们将“上下文”几乎作为一个原语来表示类似由花括号分隔的代码区域。想想代码、函数和块的主要区域(我敢打赌我已经遗漏了一些东西)。让我们从广义上考虑变量,包括变量、参数和函数名称或标识符,更一般地说。那么:
-
变量
v的范围与v可访问的上下文集相同。
这是一个例子:
let a = 'foo';
function bar(param) {
param += 2;
function newFunc() {
console.log(param);
}
newFunc();
}
这里我们有三个上下文:
- 主要背景。
- 定义
bar函数产生的上下文。 - 定义
newFunc函数产生的上下文。
根据上面的定义尝试,我们有两个作用域:
- 有像
console、null等内置名称的全局范围,以及定义的名称a和bar。此范围是上述上下文 1、2 和 3 的集合。 - 有
param和newFunc的范围。此范围是上述上下文 2 和 3 的集合。
没有范围只包含上下文 3,因为在上下文 3 中没有定义新变量。
因此,定义一个函数会创建一个上下文。变量的范围包括新的上下文,以防万一变量可以从该上下文中访问。
但是,我知道人们会说上面的代码示例包含 3 个作用域,并且或多或少地用我所说的“上下文”来标识这些作用域。但是,我无法理解这一点,并且我不知道变量范围的精确定义允许他们说上面有 3 个范围。在不谈论变量/标识符的范围的情况下谈论范围对我来说似乎很奇怪。更准确地说,似乎上下文无疑是独立于变量的,但范围不是。范围是变量/标识符的属性;这就是为什么我们在谈论作用域时谈论变量作用域或某个标识符的作用域。
我还看到人们谈论变量进出范围。对我来说,变量有一个范围,周期。程序从上下文移动到上下文,从而进出变量的范围。变量在程序运行时进出上下文。它们甚至可能总是在上下文中(如果它们具有全局作用域)或总是脱离上下文(例如,如果它们具有函数作用域并且该函数从未被调用)。但说变量进出范围或变量的范围发生变化似乎不合适。
我突然想到,除非存在可以访问标识符的唯一上下文,否则谈论标识符的 范围是不正确的。所以,相反,我们可能有
-
S 是标识符
v的a 范围,以防S 是可以访问v的上下文。
根据这个定义,我们有三个作用域:
- 上下文 1 是
a和bar的范围。 - 上下文 2 是
a、bar、param和newFunc的范围。 - 上下文 3 是
a、bar、param和newFunc的范围。
在上面的代码中,没有任何上下文确实是标识符的 范围。在这种情况下,必须有一个唯一的上下文可以访问标识符。例如,如果代码省略了newFun,则不会有第三个上下文,而上下文2 将是param 和newFunc 的 范围。
因此,定义一个函数会创建一个上下文。上下文是变量的范围,以防万一该变量可在该新上下文中访问。
不过,这里也有问题。考虑以下代码:
for (let i = 0; i < 5; i += 1) {
if (i % 2 === 0) {
console.log(i);
}
}
我看到有人说这里有三个上下文,但是 if 块的内部嵌套之一不是范围。但是根据我刚刚给出的定义,该块将是i 的范围以及像console 这样的内置函数。
这就是我目前所在的位置。提前感谢您的帮助。
更新
给定@A。 Chiesa 的回应,我写了一个short thing 来尝试理解事情。也许那个文件说得最好?再次感谢。
【问题讨论】:
-
"在不讨论变量/标识符的范围的情况下谈论范围对我来说似乎很奇怪。" 定义范围的不是变量。您可以拥有一个没有变量的功能范围。它仍然是一个有效的范围,但它是空的。
-
语言和术语是流动的。变量有范围;有人说它“超出范围”,他们只是意味着它在当前上下文中不存在。不管里面是否有任何“本地”的东西,上下文都存在——即使函数没有定义局部变量,它们也肯定有一个上下文;这就是允许闭包存在的原因。
-
我要补充一点,现阶段可能不值得这么多字,而且没有适合每个开发人员或每种语言的单一词汇。
标签: javascript scope