关于确定回调的 ,我遇到了一些关于范围界定的混淆。
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)
一切都会非常有意义。也许这就是语言的运作方式。
答案 0 :(得分:6)
JavaScript中的范围是 lexical 。如果查看示例,可以看到定义printingFunction
的位置,词法(例如,在源文本中)b
在包含范围内声明。但在你的第二个例子中,事实并非如此。这就是为什么b
在你的第二个例子中无法解决的原因,但可以在你的第一个例子中解决。
它的工作方式是,当一个函数被创建时,它有一个对包含变量的概念对象的引用,例如它在创建它的范围内(它有一个奇特的名字:“Lexical Environment object”);并且该对象具有对包含它的引用的引用。查找变量引用时,JavaScript引擎会查看当前的词法环境对象,如果找到该变量,则使用它;否则,它会查看链中的前一个,依此类推全局链接。
可以找到更多详细信息:
答案 1 :(得分:0)
问题源于我不理解function(){}
本身就是一个定义,"a"
和{}
也是如此。由于这些是定义,因此传递的函数的定义范围适当地放置在它的位置,并且世界再次有意义。
答案 2 :(得分:0)
在第一种情况下,它形成一个闭包并且可以访问变量“b”,但在第二种情况下它根本不形成闭合。如果你把一个调试器放在函数内部的cb()之前,你会注意到没有形成闭包,并且作为回调函数的原因是作为参数提供给函数,它变成了函数的本地函数。对变量b没有任何了解。
将其视为两个不同的函数,一个是局部变量“b”,另一个是局部变量但是我们试图访问它会抛出引用错误。