[英]callback function, closure and execution context
function a(callback) {
var something = 10;
callback(something);
}
a(function(blabla) {
console.log(blabla); // output 10
});
好吧,我没有理解这段代码的问题。
我知道“某些东西”是function a
本地,但是在闭包和事实意义上, 当调用函数时我会创建执行上下文,我也希望在工作之后:
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
那么究竟发生了什么(为什么第二个例子不起作用)?
显然,一切都是垃圾收集的,并且在回调函数体中无法访问。
在第二个示例中,局部变量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
对此一无所知。
函数只能引用在以下任何一个中声明的变量:
换句话说,不考虑调用范围,因此something
被认为是未定义的。
在阅读你的问题时,听起来像这里的主要困惑是为什么你可以引用something
内部a
something
,但不是在提供给a
的匿名函数内。
变量something
在函数a
的上下文中定义,而不是在匿名函数内。 因此,当您在匿名函数中引用something
时,它实际上引用了一个隐式全局变量,在这种情况下,该变量未定义。 匿名函数被放置到调用的参数列表中的事实, a
没有什么区别。
如果您意识到第二个片段大致等同于以下内容,可能会更清楚:
function a(callback) {
var something = 10;
callback();
}
function b() {
console.log(something);
}
a(b);
所以你可以清楚地看到这两个完全不相关的函数,它们有自己的范围。
在你的第一个例子中: -
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,并且回调函数不可用
简短的回答:在第二个例子中的回调产生的闭合,将寻找全局变量something
不存在。
比。 第一个例子周围产生可变的封闭something
中的功能a
。 如果something
的值发生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"
当你定义一个函数为inline它会创建自己的范围,并引用了一个局部变量something
。
由于内联函数没有捕获它,函数a
传递的something
会被删除。 在一些更严格的语言中,它会抛出一个错误,但JS却没有。
内联函数试图console.log
局部变量something
,这是没有找到。 搜索全局范围并找到“Global something”并打印它。 局部变量没有闭包。
a( function(x) {console.log(x)} ); //"Local something"
内联函数创建并引用局部变量x
。
但是x
指向函数a
传递的something
变量,而something
变量又指向“本地东西”,它被打印出来。 关闭局部变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.