[英]Access local variable inside a callback function
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); }
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
具有什么值(在函数的声明中),在使用inner
函数时,稍后将是x
变量的可用值。 您的x
未定义的事实只是一个附件,并不是导致不良行为的原因。
所以,当您在任何IIFE中调用inner
函数时, inner
函数声明中引用的x
是x
在定义函数时作为值的捕获值,而不是x
具有的值现在在当前调用函数的范围内。 这就是所谓的词法范围 。
要解决这个问题,你必须将inner
函数中的console.log()
值作为参数传递给inner
函数,如下所示:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);
在回调中访问局部变量x
的唯一方法是将其作为参数传递:
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb(x); })(inner);
要么
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);
要么
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);
进一步
因为JS是词法范围的,所以在匿名函数完成执行后尝试引用局部变量是不可能通过任何其他方法。 如果你没有将它作为参数传递给其他地方使用,那么JS会将其视为不可访问的,并且它将有资格进行垃圾回收。
您可以在当前范围中重新定义回调函数:
var inner = function() { console.log(x); }
(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner);
// or
(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner);
如果函数依赖于最初定义范围内的任何内容或者Javascript文件已缩小,则此方法无效。 使用eval
可能会带来安全性,性能和代码质量问题。
你尝试过使用过活动吗? 在匿名函数中发出一个事件,然后在你自己的函数中订阅它,执行你的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.