回调定义关闭问题

Ret*_*n-1 0 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
Run Code Online (Sandbox Code Playgroud)

但是,以下不起作用

function test(){

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

    return fun
}

test()(function(){console.log(b)}) //b is not defined
Run Code Online (Sandbox Code Playgroud)

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


编辑:一些额外的指针.

someFunction("a")
Run Code Online (Sandbox Code Playgroud)

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

同样,我们不能声称{}是一个定义:someFunction({}).那么为什么会:

someFunction(function(){})

决定这function(){}是一个超越我的定义.如果是的话

var a = function(){}
someFunction(a)
Run Code Online (Sandbox Code Playgroud)

一切都会很有道理.也许它只是语言的运作方式.

T.J*_*der 6

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

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

更多细节可以找到: