OOJavaScript:变量作用域的明确解释
有人能解释一下JS中变量作用域在对象、函数和闭包中的应用吗 未使用var声明的变量在作用域中是全局变量。 函数引入范围,但请注意,如果块和其他块不引入范围 通过谷歌搜索Javascript范围,我也可以看到很多关于这方面的信息。这正是我的建议。 全局变量 Javascript中的每个变量都是对象的命名属性。例如:-OOJavaScript:变量作用域的明确解释,javascript,oop,Javascript,Oop,有人能解释一下JS中变量作用域在对象、函数和闭包中的应用吗 未使用var声明的变量在作用域中是全局变量。 函数引入范围,但请注意,如果块和其他块不引入范围 通过谷歌搜索Javascript范围,我也可以看到很多关于这方面的信息。这正是我的建议。 全局变量 Javascript中的每个变量都是对象的命名属性。例如:- var x = 1; x被添加到全局对象。全局对象由脚本上下文提供,可能已经有一组属性。例如,在浏览器中,全局对象是窗口。与浏览器中的上述行等效的是:- window.x = 1;
var x = 1;
x被添加到全局对象。全局对象由脚本上下文提供,可能已经有一组属性。例如,在浏览器中,全局对象是窗口。与浏览器中的上述行等效的是:-
window.x = 1;
局部变量
现在,如果我们将其更改为:-
function fn()
{
var x = 1;
}
当调用
fn
时,将创建一个新对象,称为执行上下文,也称为范围(我可以互换使用这些术语)x
作为属性添加到此范围对象。因此,对fn
的每次调用都将获得其自己的范围对象实例,从而获得附加到该范围对象的x属性实例
关闭
现在让我们更进一步:-
function fnSequence()
{
var x = 1;
return function() { return x++; }
}
var fn1 = fnSequence();
var fn2 = fnSequence();
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn2())
注意:用上下文中写入stdout的内容替换WScript.Echo
您应该获得的顺序是:-
123434
那么这里发生了什么?我们有fnSequence
,它将变量x
初始化为1,并返回一个匿名函数,该函数将返回x
的值,然后将其递增
首次执行此函数时,将创建一个范围对象,并向该范围对象添加一个值为1的属性x
。在同一执行对象中还创建了一个匿名函数。每个函数对象都有一个scope属性,该属性指向创建它的执行上下文。这创建了一个范围链,我们将在后面介绍。此函数的引用由fnSequence
返回并存储在fn1
中
请注意,fn1
现在指向匿名函数,并且匿名函数有一个作用域属性,该属性指向仍然附加了x
属性的作用域对象。这称为closure
,其中在为其创建的函数完成执行后,仍然可以访问执行上下文的内容
现在,当分配给fn2
时,同样的顺序也会发生fn2
将指向在第二次调用fnSequence
时创建的不同执行上下文中创建的不同匿名函数
范围链
第一次执行fn1
持有的函数时会发生什么情况?将为匿名函数的执行创建一个新的执行上下文。可以从标识符x
中找到返回值。检查函数的范围对象是否有x
属性,但未找到任何属性。这就是范围链的意义所在。在当前执行上下文中找不到x
之后,JavaScript获取函数的scope属性所持有的对象,并在那里查找x
。由于函数作用域是在执行fnSequence
时创建的,因此它会找到它,检索它的值并递增它。因此,输出1,该范围内的x
增加到2
现在,当执行fn2
时,它最终会附加到另一个执行上下文,该上下文的x
属性仍然为1。因此执行fn2
也会导致1
如您所见,
fn1
和fn2
分别生成各自独立的数字序列。函数引入了一个作用域。您可以在其他函数中声明函数,从而创建嵌套范围。内部作用域可以访问外部作用域,但外部作用域不能访问内部作用域
使用var关键字将变量绑定到一个范围。所有变量都隐式绑定到顶级范围。因此,如果省略var关键字,则隐式引用绑定到顶层的变量。在浏览器中,顶层是窗口对象。请注意,window本身是一个变量,因此window=window。window这个答案确实不精确<代码>变量x=1代码>和
窗口。x=1代码>不是等效的。在第二种情况下,x
是可删除的。首先,事实并非如此。使用术语“attribute”而不是“variable”或“property”是没有帮助的,因为“attribute”对于JavaScript开发人员已经有两种含义,而您正在使用的两种含义都不是。此外,您对执行上下文的描述是错误的:如果要使用ECMAScript规范中的术语,那么您确实需要准确地使用它们。[续]调用fn
时,将创建x
作为变量对象的属性,该变量对象绑定到执行上下文,但与执行上下文不同。将术语“范围”与“执行上下文”互换使用也无济于事:同样,它们是密切相关的,每个执行上下文都有一个范围链,但它们不是一回事。例如,执行上下文中的代码可能会通过使用with
语句或catch
子句来更改作用域链。很抱歉,批评:您所说的大致正确,但您使用ECMAScript规范中的术语解释得不准确。@Tim:我接受您所有的批评。然而,我发现,超精细的精度虽然能够澄清最细微的行为,但只有聪明的BOD才能正确吸收。我们这些凡人都茫然地看着。我被烧伤过很多次