Javascript 访问回调函数内的局部变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26590830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:06:40  来源:igfitidea点击:

Access local variable inside a callback function

javascriptnode.js

提问by Jacob

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

All tests result in: ReferenceError: x is not defined

所有测试结果:ReferenceError: x is not defined

Do someone know how it is possible to access 'x' as a local variable inside the callback?

有人知道如何在回调中访问 'x' 作为局部变量吗?

回答by Rafael Eyng

Fact: when you do var inner = function() { console.log(x); }in your first line, xis not defined. Why? Because, inside your innerfunction, there's no local declaration of x (which would be done with var x = something). The runtime will then look up in the next scope, that is the global scope. There isn't, also, a declaration of x, so xis also not defined there.

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

The only places where there is a variable called xare inside each one of your 4 IIFEs following. But inside the IIFEs, each xis a different variable, in a different scope. So, if what you want is to console.log()the xdefined inside each IIFE, you are taking the wrong approach.

唯一有变量被调用的地方x是在接下来的 4 个 IIFE 中的每一个内部。但是在 IIFE 内部,每个x变量都是不同的变量,在不同的范围内。因此,如果您想要的是每个 IIFE 中console.log()x定义,那么您就采取了错误的方法。

Keep in mind that, when you define inner, you are capturing the environment inside the function's closure. It means that, whatever value could xhave there (in the declaration of the function), would be the available value to the xvariable later, when the innerfunction would be used. The fact that your xthere is not defined is only an accessory, and is not what is causing the undesired behavior.

请记住,当您定义 时inner,您正在捕获函数闭包内的环境。这意味着,无论x在那里(在函数的声明中)可能具有的任何值,都将是x稍后使用该inner函数时变量的可用值。您x没有定义的事实只是一个附件,而不是导致不良行为的原因。

So, what happens is that when you call your innerfunction inside any of your IIFEs, the xreferred to inside the innerfunction declaration is a captured value of what xhad as a value when the function was defined, not the value that xhas now in the scope where the function is currently being called. This is what is called lexical scope.

因此,发生的情况是,当您inner在任何 IIFE 中调用您的函数时,在函数声明中x引用的是在定义函数时作为值inner的捕获值,而不是现在在其中的作用域中的值当前正在调用该函数。这就是所谓的词法范围xx

To solve this, you would have to pass the value that you want to console.log()inside the innerfunction as a parameter to the innerfunction, as so:

为了解决这个问题,你就必须要通过价值console.log()内部inner函数作为参数传递给inner函数,像这样:

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

回答by Adam

The only wayto access the local variable xin the callback, is to pass it as an argument:

在回调中访问局部变量的唯一方法x是将其作为参数传递:

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

OR

或者

var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);

OR

或者

var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);

FURTHER

更远

Because JS is lexically scoped, trying to reference the local variable after the anonymous function has finished executing is impossible by any other means. If you don't pass it as an argument to make it available elsewhere, JS will see it as non-reachable and it will be eligible for garbage collection.

因为 JS 是词法作用域的,在匿名函数执行完成后尝试引用局部变量是不可能的。如果您不将其作为参数传递以使其在其他地方可用,则 JS 会将其视为不可访问的,并且有资格进行垃圾收集。

回答by Nick Barry

You could redefine the callback function in the current scope:

您可以在当前范围内重新定义回调函数:

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

This will not work if the function relies on anything in the scope in which it was originally defined or if the Javascript file has been minified. The use of evalmay introduce security, performance, and code quality issues.

如果函数依赖于它最初定义的范围内的任何东西,或者如果 Javascript 文件已经被缩小,这将不起作用。的使用eval可能会引入安全性、性能和代码质量问题。

回答by Bellatorius

Have you tried using events? Emit an event inside the anonymous function, then subscribe to it in your own function somewhere else that carries out your logic.

您是否尝试过使用事件?在匿名函数内发出一个事件,然后在您自己的函数中订阅它以执行您的逻辑。