回调定义关闭问题

时间:2018-03-05 08:35:08

标签: javascript closures

关于确定回调的 ,我遇到了一些关于范围界定的混淆。

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

但是,以下不起作用

function test(){

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

    return fun
}

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

我希望由于函数作为参数传递并且尚未在之前定义,因此它的定义发生在'fun'中,因此它可以访问b。相反,它看起来很像函数首先在其传递的范围中定义,然后THEN作为参数传递。任何想法/指针?

编辑:一些额外的指示。

someFunction("a")

我们不可能声称“a”是一个定义。这里隐含的是“a”被赋值给由参数名称命名的变量var argumentNameInDefintion = "a"。这发生在someFunction的主体中。

同样,我们无法声明{}someFunction({})中的定义。那么为什么会:

someFunction(function(){})

决定function(){}是一个超出我的定义。如果是

var a = function(){}
someFunction(a)
一切都会非常有意义。也许这就是语言的运作方式。

3 个答案:

答案 0 :(得分:6)

JavaScript中的范围是 lexical 。如果查看示例,可以看到定义printingFunction的位置,词法(例如,在源文本中)b在包含范围内声明。但在你的第二个例子中,事实并非如此。这就是为什么b在你的第二个例子中无法解决的原因,但可以在你的第一个例子中解决。

它的工作方式是,当一个函数被创建时,它有一个对包含变量的概念对象的引用,例如它在创建它的范围内(它有一个奇特的名字:“Lexical Environment object”);并且该对象具有对包含它的引用的引用。查找变量引用时,JavaScript引擎会查看当前的词法环境对象,如果找到该变量,则使用它;否则,它会查看链中的前一个,依此类推全局链接。

可以找到更多详细信息:

答案 1 :(得分:0)

问题源于我不理解function(){}本身就是一个定义,"a"{}也是如此。由于这些是定义,因此传递的函数的定义范围适当地放置在它的位置,并且世界再次有意义。

答案 2 :(得分:0)

在第一种情况下,它形成一个闭包并且可以访问变量“b”,但在第二种情况下它根本不形成闭合。如果你把一个调试器放在函数内部的cb()之前,你会注意到没有形成闭包,并且作为回调函数的原因是作为参数提供给函数,它变成了函数的本地函数。对变量b没有任何了解。

将其视为两个不同的函数,一个是局部变量“b”,另一个是局部变量但是我们试图访问它会抛出引用错误。