简体   繁体   English

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

[英]callback function, closure and execution context

function a(callback) {
    var something = 10;

    callback(something);
}

a(function(blabla) {
    console.log(blabla); // output 10
});

Ok i dont have problem understanding this code. 好吧,我没有理解这段代码的问题。

I know that "something" is local to function a and but in the sense of closures and fact that execution context is created when function is called i expected following to work also: 我知道“某些东西”是function a本地,但是在闭包和事实意义上, 当调用函数时我会创建执行上下文,我也希望在工作之后:

function a(callback) { 
    var something = 10; 

    callback(); 
} 

a(function() { 
    console.log(something); 
}); 

So what happened exactly (why second example don't work)? 那么究竟发生了什么(为什么第二个例子不起作用)?
Obviously everything is garbage collected and not accessible in body of callback function. 显然,一切都是垃圾收集的,并且在回调函数体中无法访问。

In the second example, the local variable something is not accessible in the body of your callback not because it's garbage collected, but simply because it is out of scope. 在第二个示例中,局部变量something在回调体中是不可访问的,不是因为它是垃圾收集,而是因为它超出了范围。

Consider this counter-example: 考虑这个反例:

function a(callback) { 
    callback(); 
} 

var something = 10; 

a(function() { 
    console.log(something); 
});

Here something is in scope at the time the body of the callback is defined so you can reference it. 这里有something在定义回调体的范围内,所以你可以引用它。 Doing so creates a closure. 这样做可以创建一个闭包。

Also consider this one: 还要考虑这个:

function foo() {
    var xyz = 1;
    bar();
}

function bar() {
    console.log(xyz);
}

This is functionally the same example as you have: foo is a and bar is the anonymous function passed in as callback . 这在功能上与您拥有的示例相同: fooabar是作为callback传入的匿名函数。

Why should calling bar() result in printing 1 here? 为什么调用bar()导致打印1 That variable is locally scoped inside foo , and bar knows nothing about it. 该变量在foo本地作用域,而bar对此一无所知。

A function can only reference variables that are declared in either: 函数只能引用在以下任何一个中声明的变量:

  1. the function body, 功能体,
  2. the function arguments (applies in 1st example), 函数参数(适用于第一个例子),
  3. the scope where the function was declared. 声明函数的范围。

In other words, the calling scope is not taken into account and so something is considered undefined. 换句话说,不考虑调用范围,因此something被认为是未定义的。

In reading your question, it sounds to me like the primary confusion here is in why you can reference something inside a , but not inside the anonymous function provided to a . 在阅读你的问题时,听起来像这里的主要困惑是为什么你可以引用something内部a something ,但不是在提供给a的匿名函数内。

The variable something is defined within the context of the function a , not within the anonymous function. 变量something在函数a的上下文中定义,而不是在匿名函数内。 So when you reference something inside the anonymous function, it actually references an implicit global variable, which in this case is not defined. 因此,当您在匿名函数中引用something时,它实际上引用了一个隐式全局变量,在这种情况下,该变量未定义。 The fact that the anonymous function is placed within the parameter list of a call to a makes no difference. 匿名函数被放置到调用的参数列表中的事实, a没有什么区别。

Perhaps it would be more clear if you realize that the second snippet is roughly equivalent to: 如果您意识到第二个片段大致等同于以下内容,可能会更清楚:

function a(callback) { 
    var something = 10; 

    callback(); 
} 

function b() { 
    console.log(something); 
}

a(b); 

So you can see clearly these are two completely unrelated functions, with their own scopes. 所以你可以清楚地看到这两个完全不相关的函数,它们有自己的范围。

In your first example:- 在你的第一个例子中: -

function a(callback) {
    var something = 10;

    callback(something);
}

a(function(blabla) {
    console.log(blabla); // output 10
});

blabla is a variable which is available to the anonymous function passed as parameter to a. blabla是一个变量,可以作为参数传递给a的匿名函数。 So something is passed to callback function as function parameter and is hence available to function under name blabla. 因此,某些东西作为函数参数传递给回调函数,因此可以在名称blabla下运行。

But in second example:- 但在第二个例子中: -

function a(callback) { 
    var something = 10; 

    callback(); 
} 

a(function() { 
    console.log(something); 
}); 

something is unknown to the function as its not a global variable/ is not a function parameter. 函数不知道某些东西,因为它不是全局变量/不是函数参数。

So this is a js error as you are trying to access an undefined variable. 因此,当您尝试访问未定义的变量时,这是一个js错误。

So scope of something is limited to the function a and is not available to the callback function 因此,某些东西的范围仅限于函数a,并且回调函数不可用

Short answer: The closure created by the callback in the second example, will look for the global variable something which does not exist. 简短的回答:在第二个例子中的回调产生的闭合,将寻找全局变量something不存在。

Vs. 比。 the first example creates a closure around the variable something within function a . 第一个例子周围产生可变的封闭something中的功能a If the value of something is mutated, calling a again will produce a different value. 如果something的值发生something变异,再次调用a将产生不同的值。

Consider the following different ways to pass callback functions: 考虑以下不同的方式来传递回调函数:

var something = "Global something";

function a(callback) {
   var something = "Local something";
   callback(something);
}

a( console.log ); // "Local something"

As defined, console.log() will accept the something passed by function a as its first argument and prints it out to the screen. 根据定义, console.log()将接受something通过函数传递a作为第一个参数,并把它打印输出到屏幕上。 Closure happens on the local variable. 关闭发生在局部变量上。

a( function() {console.log(something)} ); //"Global something"

When you define a function inline it creates its own scope, and references a local variable something . 当你定义一个函数为inline它会创建自己的范围,并引用了一个局部变量something

The something passed by function a gets dropped as the inline function did not catch it. 由于内联函数没有捕获它,函数a传递的something会被删除。 In some stricter languages it will throw an error, but JS does not. 在一些更严格的语言中,它会抛出一个错误,但JS却没有。

The inline function tries to console.log the local variable something , which is not found. 内联函数试图console.log局部变量something ,这是没有找到。 Searches global scope and finds "Global something" and prints it. 搜索全局范围并找到“Global something”并打印它。 No closure on the local variable. 局部变量没有闭包。

a( function(x) {console.log(x)} ); //"Local something"

The inline function creates and references local variable x . 内联函数创建并引用局部变量x

But x points to the something variable passed by function a , which in turn which points to "Local something", which gets printed. 但是x指向函数a传递的something变量,而something变量又指向“本地东西”,它被打印出来。 Closure on the local variable. 关闭局部变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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