访问回调函数中的局部变量
var inner = function() { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(); })(inner);
// test 2
(function(cb) { var x = 123; cb.apply(this); })(inner);
// test 3
(function(cb) { var x = 123; cb.bind(this)(); })(inner);
// test 4
(function(cb) { cb.bind({x: 123})(); })(inner);
所有测试都会导致:ReferenceError:未定义x
有人知道如何在回调中访问'x'作为局部变量吗?
回答如下:事实:当你在第一行中执行var inner = function() { console.log(x); }
时,没有定义x
。为什么?因为,在你的inner
函数里面,没有x的局部声明(可以用var x = something
完成)。然后,运行时将在下一个范围中查找,即全局范围。还没有关于x
的声明,所以x
也没有在那里定义。
唯一有一个名为x
的变量的地方就在你的4个IIFE中的每一个之后。但在IIFE中,每个x
都是一个不同的变量,在不同的范围内。所以,如果你想要的是console.log()
在每个IIFE中定义的x
,你采取了错误的方法。
请记住,当您定义inner
时,您正在捕获函数闭包内的环境。这意味着,无论x
有什么价值(在函数的声明中),当使用x
函数时,将是inner
变量的可用值。你的x
没有定义的事实只是一个附件,并不是导致不良行为的原因。
所以,当你在你的任何IIFE中调用你的inner
函数时,x
函数声明中引用的inner
是x
在定义函数时具有的值的捕获值,而不是x
具有的值现在在当前调用函数的范围内。这就是所谓的词法范围。
要解决这个问题,你必须将console.log()
函数中的inner
值作为参数传递给inner
函数,如下所示:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);