function a(callback) {
var something = 10;
callback(something);
}
a(function(blabla) {
console.log(blabla); // output 10
});
好的,我没有理解这段代码的问题。
我知道“某些东西”是function a
的本地,但是在封闭的意义上,以及在调用函数时创建执行上下文的事实我希望以下工作:< / p>
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
那究竟发生了什么(为什么第二个例子不起作用)?
显然,所有内容都是垃圾回收,无法在回调函数体中访问。
答案 0 :(得分:4)
在第二个示例中,局部变量something
在回调体中是不可访问的,不是因为它是垃圾收集,而只是因为它超出了范围。
考虑这个反例:
function a(callback) {
callback();
}
var something = 10;
a(function() {
console.log(something);
});
此处something
在定义回调正文时在范围内,因此您可以引用它。这样做会创建一个闭包。
还要考虑这个:
function foo() {
var xyz = 1;
bar();
}
function bar() {
console.log(xyz);
}
这在功能上与您的示例相同:foo
为a
,bar
是以callback
传入的匿名函数。
为什么要调用bar()
导致在此处打印1
?该变量位于foo
内的本地范围内,bar
对此一无所知。
答案 1 :(得分:2)
一个函数只能引用在以下任何一个中声明的变量:
换句话说,调用范围不会被考虑在内,因此something
被视为未定义。
答案 2 :(得分:1)
在阅读你的问题时,听起来像这里的主要混淆是为什么你可以在something
内引用a
,而不是在a
提供的匿名函数中引用。< / p>
变量something
是在函数a
的上下文中定义的,而不是在匿名函数中定义的。因此,当您在匿名函数中引用something
时,它实际上引用了一个隐式全局变量,在这种情况下,该变量未定义。匿名函数放在a
调用的参数列表中这一事实没有任何区别。
如果您意识到第二个片段大致等同于:
,也许会更清楚function a(callback) {
var something = 10;
callback();
}
function b() {
console.log(something);
}
a(b);
所以你可以清楚地看到这两个完全不相关的函数,它们有自己的范围。
答案 3 :(得分:1)
在你的第一个例子中: -
function a(callback) {
var something = 10;
callback(something);
}
a(function(blabla) {
console.log(blabla); // output 10
});
blabla是一个变量,可以作为参数传递给a的匿名函数。因此,某些东西作为函数参数传递给回调函数,因此可以在名称blabla下运行。
但在第二个例子中: -
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
函数不知道某些东西,因为它不是全局变量/不是函数参数。
因此,当您尝试访问未定义的变量时,这是一个js错误。
因此,某些内容的范围仅限于函数a,并且回调函数无法使用
答案 4 :(得分:0)
简短回答:
由第二个示例中的回调创建的闭包将查找不存在的全局变量something
。
Vs以上。第一个示例在函数something
中围绕变量a
创建一个闭包。如果something
的值发生变异,再次调用a
将产生不同的值。
考虑以下不同的方式来传递回调函数:
var something = "Global something";
function a(callback) {
var something = "Local something";
callback(something);
}
a( console.log ); // "Local something"
根据定义,console.log()
将接受函数something
传递的a
作为其第一个参数,并将其打印到屏幕上。 关闭发生在局部变量上。
a( function() {console.log(something)} ); //"Global something"
当您定义函数内联时,它会创建自己的范围,并引用局部变量something
。
函数something
传递的a
被删除,因为内联函数没有捕获它。
在一些更严格的语言中,它会引发错误,但JS不会。
内联函数尝试console.log
找不到的局部变量something
。搜索全局范围并找到“Global something”并打印它。 本地变量没有关闭。
a( function(x) {console.log(x)} ); //"Local something"
内联函数创建并引用局部变量x
。
但是x
指向由函数something
传递的a
变量,而该变量又指向“本地内容”,后者会被打印出来。 关闭局部变量。