在callback函数中访问局部variables

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); 

所有的testing结果如下:ReferenceError:x没有定义

是否有人知道如何在callback中访问“x”作为局部variables?

事实:当你做var inner = function() { console.log(x); } var inner = function() { console.log(x); }在你的第一行中, x没有被定义。 为什么? 因为在你的inner函数中,没有x的局部声明(这可以用var x = something来完成)。 然后,运行时将查找下一个作用域,即全局作用域。 也没有x的声明,所以x也没有在那里定义。

唯一的地方有一个名为x的variables是在你的4个IIFE中的每一个里面。 但是在IIFE中,每个x都是一个不同的variables,处于不同的范围。 所以,如果你想要的是console.log()在每个IIFE中定义的x ,你正在采取错误的方法。

请记住,当你定义inner ,你正在捕获函数闭包内的环境。 这意味着,无论函数声明中的x值是什么,在inner函数被使用的时候, xvariables的可用值都将是xvariables的可用值。 事实上,你的x没有定义只是一个附件,而不是什么导致不良行为。

所以,当你在你的任何一个IIFE中调用你的inner函数时,会发生什么情况呢,在inner函数声明中引用的x是函数被定义x作为一个值的捕获值,而不是x具有的值现在在函数被调用的范围内。 这就是所谓的词汇范围

为了解决这个问题,你需要将inner函数中的console.log()的值作为parameter passing给inner函数,如下所示:

 var inner = function(x) { console.log(x); } // test 1 (function(cb) { var x = 123; cb(x); })(inner); 

访问callback中的局部variablesx唯一方法是将其作为parameter passing:

 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在词汇范围上,试图在匿名函数执行完成后引用局部variables是不可能的。 如果你不把它作为parameter passing给其他地方,JS会认为它是不可访问的,它将有资格进行垃圾回收。

您可以重新定义当前范围中的callback函数:

 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); 

如果函数依赖于最初定义的范围内的任何内容,则这将不起作用,并且使用eval可能会引入安全性,性能和代码质量问题。