繁体   English   中英

回调函数,闭包和执行上下文

[英]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);
}

这在功能上与您拥有的示例相同: fooabar是作为callback传入的匿名函数。

为什么调用bar()导致打印1 该变量在foo本地作用域,而bar对此一无所知。

函数只能引用在以下任何一个中声明的变量:

  1. 功能体,
  2. 函数参数(适用于第一个例子),
  3. 声明函数的范围。

换句话说,不考虑调用范围,因此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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM