简体   繁体   English

回调定义关闭问题

[英]Callback definition closure issue

I run into a bit of confusion regarding scoping with respect to where a callback is defined . 关于定义回调的作用域,我遇到了一些混乱。

function test(){

    var b = 3
    var fun = function(){

        var printingFunction = function(){
            console.log(b)
        }
        printingFunction()
    }

    return fun
}

test()() //prints 3, as expected because of closures

However, the following doesnt work 但是,以下方法不起作用

function test(){

    var b = 3
    var fun = function(cb){
        cb()
    }

    return fun
}

test()(function(){console.log(b)}) //b is not defined

I would expect that since the function is passed as an argument and has not been defined before , its definition takes place inside 'fun' and therefore it would have access to b. 我希望由于函数是作为参数传递的, 并且之前未定义 ,因此它的定义发生在“ fun”内部,因此可以访问b。 Instead, it looks a lot like the function is first defined in the scope where its passed and THEN passed as an argument. 相反,它看起来很像是函数首先在作用域中定义,然后将其作为参数传递。 Any ideas/pointers? 有任何想法/指标吗?


EDIT: Some extra pointers. 编辑:一些额外的指针。

someFunction("a")

We couldn't possibly claim that "a" is a definition. 我们不可能声称“ a”是一个定义。 What happens here implicitly is that "a" is assigned to a variable named by the argument name so var argumentNameInDefintion = "a" . 这里隐式发生的是,将“ a”分配给以参数名称命名的变量,因此var argumentNameInDefintion = "a" This happens in the body of someFunction. 这发生在someFunction的主体中。

Similarly we cant claim {} is a definition in : someFunction({}) . 同样,我们不能声称{}是在someFunction({})的定义。 So why would: 那么为什么会:

someFunction(function(){})

decide that function(){} is a definition is beyond me. 决定function(){}是一个定义超出了我。 Had it been 曾经

var a = function(){}
someFunction(a)

everything would make perfect sense. 一切都会说得通。 Maybe its just how the language works. 也许这就是语言的工作方式。

Scoping in JavaScript is lexical . JavaScript中的作用域是词汇上的 If you look at your examples, you can see that where printingFunction is defined, lexically (eg, in the source text) b is declared in a containing scope. 如果你看一下你的例子,你可以看到,这里printingFunction定义,词汇(例如,在源文本) b是一个包含范围内声明。 But in your second example, it isn't. 但是在第二个示例中,事实并非如此。 That's why b can't be resolved in your second example but can in your first. 这就是为什么b在您的第二个示例中无法解决,而在您的第一个示例中可以解决。

The way it works is that when a function is created, it has a reference to a conceptual object containing the variables and such in the scope in which it's created (which has a fancy name: "Lexical Environment object"); 它的工作方式是,在创建函数时,它引用了包含变量的概念对象,并且在创建对象的范围内也是如此(它的名字叫“ Lexical Environment object”)。 and that object has a reference to the one that contains it. 并且该对象引用了包含该对象的对象。 When looking up a variable reference, the JavaScript engine looks at the current lexical environment object and, if it finds the variable, uses it; 当查找变量引用时,JavaScript引擎将查看当前的词法环境对象,如果找到该变量,则使用它。 otherwise, it looks to the previous one in the chain, and so on up to the global one. 否则,它会寻找链中的前一个,依此类推,直到全局。

More details can be found: 可以找到更多详细信息:

The issue stems from me not understanding that function(){} on its own is a definition and so is "a" and {} . 问题源于我不了解function(){}本身是一个定义,而"a"{} Since these are definitions then the definition scope of the function passed is appropriately placed where it is and the world makes sense again. 由于这些是定义,因此将传递的函数的定义范围适当地放在原处,世界再次变得有意义。

In first case, it is forming a closure and has access to the variable "b" but in second case it does not form a closure at all. 在第一种情况下,它正在形成一个闭合并且可以访问变量“ b”,但是在第二种情况下,它根本没有形成闭合。 If you put a debugger just before the cb() inside the function, you will notice that there is no closure formed and the reason of that being the callback function is suplied to the function as an argument and it becomes local to that function which does not have any knowledge of the variable b. 如果将调试器放在函数内部的cb()之前,您会注意到没有形成闭包,并且将回调函数作为参数提供给该函数的原因是它成为该函数的局部参数,不了解变量b。

Think of it as two different functions, one in which it has a local variable "b" and in other no local variable but we are trying to access it which throws the reference error. 可以将其视为两个不同的函数,其中一个具有局部变量“ b”,而另一个没有局部变量,但是我们试图访问它会引发参考错误。

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

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