Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OOJavaScript:变量作用域的明确解释_Javascript_Oop - Fatal编程技术网

OOJavaScript:变量作用域的明确解释

OOJavaScript:变量作用域的明确解释,javascript,oop,Javascript,Oop,有人能解释一下JS中变量作用域在对象、函数和闭包中的应用吗 未使用var声明的变量在作用域中是全局变量。 函数引入范围,但请注意,如果块和其他块不引入范围 通过谷歌搜索Javascript范围,我也可以看到很多关于这方面的信息。这正是我的建议。 全局变量 Javascript中的每个变量都是对象的命名属性。例如:- var x = 1; x被添加到全局对象。全局对象由脚本上下文提供,可能已经有一组属性。例如,在浏览器中,全局对象是窗口。与浏览器中的上述行等效的是:- window.x = 1;

有人能解释一下JS中变量作用域在对象、函数和闭包中的应用吗

未使用var声明的变量在作用域中是全局变量。 函数引入范围,但请注意,如果块和其他块不引入范围

通过谷歌搜索Javascript范围,我也可以看到很多关于这方面的信息。这正是我的建议。

全局变量 Javascript中的每个变量都是对象的命名属性。例如:-

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才能正确吸收。我们这些凡人都茫然地看着。我被烧伤过很多次