javascript中变量的范围是什么?它们在函数内部的作用域与在函数外部的作用域相同吗?或者这有关系吗?此外,如果变量是全局定义的,那么变量存储在哪里?


当前回答

Javascript使用作用域链为给定函数建立作用域。通常有一个全局范围,每个定义的函数都有自己的嵌套范围。在另一个函数中定义的任何函数都具有与外部函数链接的局部作用域。定义范围的始终是源代码中的位置。

作用域链中的元素基本上是一个带有指向其父作用域指针的Map。

解析变量时,javascript从最内部的范围开始并向外搜索。

其他回答

我很喜欢接受的答案,但我想补充一点:

作用域收集并维护所有声明的标识符(变量)的查找列表,并对当前执行的代码如何访问这些标识符实施一组严格的规则。

作用域是一组按标识符名称查找变量的规则。

如果在直接作用域中找不到变量,引擎将继续查询下一个外部包含作用域,直到找到或到达最外部(即全局)作用域。是一组规则,用于确定在何处以及如何查找变量(标识符)。该查找可能用于分配变量,该变量是LHS(左侧)参考,也可能用于检索其值,该值是RHS(右侧)参考。LHS引用源于赋值操作。与作用域相关的赋值可以使用=运算符进行,也可以通过将参数传递给(赋值给)函数参数进行。JavaScript引擎在执行代码之前首先编译代码,在这样做的过程中,它会拆分像vara=2这样的语句;分为两个单独的步骤:第一步。首先,var a在该范围中声明它。这是在代码执行之前开始执行的。第二。稍后,a=2查找变量(LHS引用),如果找到,则将其赋值。LHS和RHS引用查找都从当前执行的作用域开始,如果需要的话(也就是说,它们找不到它们在那里寻找的对象),它们会在嵌套作用域中一次一个作用域(层)查找标识符,直到它们到达全局(顶层)并停止,然后要么找到,要么不找到。未完成的RHS引用导致引发ReferenceError。未完成的LHS引用将导致该名称的自动隐式创建的全局(如果不在严格模式下),或ReferenceError(如果在严格模式中)。作用域由一系列“气泡”组成,每个气泡充当容器或桶,其中声明了标识符(变量、函数)。这些气泡整齐地嵌套在彼此内部,这种嵌套是在作者时定义的。

全局声明的变量具有全局范围。在函数中声明的变量的作用域是该函数,并隐藏同名的全局变量。

(我相信真正的JavaScript程序员可以在其他答案中指出许多微妙之处。特别是我在这个页面上看到了这到底意味着什么。不过,希望这个更为介绍性的链接足以让你开始。)

试试这个奇怪的例子。在下面的示例中,如果a是一个初始化为0的数字,您将看到0,然后是1。除了a是一个对象,javascript将向f1传递a的指针,而不是它的副本。结果是两次都得到相同的警报。

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());

Javascript使用作用域链为给定函数建立作用域。通常有一个全局范围,每个定义的函数都有自己的嵌套范围。在另一个函数中定义的任何函数都具有与外部函数链接的局部作用域。定义范围的始终是源代码中的位置。

作用域链中的元素基本上是一个带有指向其父作用域指针的Map。

解析变量时,javascript从最内部的范围开始并向外搜索。

现代J、ES6+、“const”和“let”

您应该像大多数其他主要语言一样,为创建的每个变量使用块范围。var已过时。这使您的代码更安全,更易于维护。

95%的病例应使用常量。它使变量引用不能更改。数组、对象和DOM节点财产可以更改,并且应该是常量。

let应该用于任何期望重新分配的变量。这包括在for循环中。如果在初始化之后更改值,请使用let。

块范围意味着变量只能在声明它的括号内使用。这扩展到内部范围,包括在范围内创建的匿名函数。