JavaScript 闭包和回调函数

标签 javascript callback closures

有人可以帮我澄清这一点吗?

JavaScript 中我最喜欢的两个功能是闭包和函数是第一类对象这一事实。

如果我想在回调函数中利用闭包,那么该函数必须始终是内部函数。例如:

doNested();
function doNested() {
    var message='Hello';
    window.setTimeout(inner, 3000);
    function inner() {
        alert(message);
    }
}

我无法将参数传递给外部回调函数。例如:

doSeparated();
function doSeparated() {
    var message='Goodbye';
    window.setTimeout(outer,3000);
}
function outer() {
    alert(message);
}

当然,这是行不通的。

问题是,除了将内部变量添加到参数列表之外,是否有任何方法可以将内部变量传递给这样的外部函数?

谢谢

最佳答案

If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function.

这是正确的。 JavaScript 中的每个函数只能访问在其自身作用域中定义或在父作用域中定义的变量1。因此,您的第一个示例有效,而第二个示例则无效。

The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?

不,没有办法做到这一点。好吧,从技术上讲,您可以将内部变量添加到一个对象,然后将该对象绑定(bind)到外部函数,然后您可以从外部函数的 this 上下文访问内部变量函数,但这并不比直接将变量传递给函数更好。

doSeparated();

function doSeparated() {
    var message = "Goodbye";

    setTimeout(outer.bind({
        message: message
    }), 3000);
}

function outer() {
    alert(this.message);
}

由于您使用的是 setTimeout,因此您可以将额外的参数传递给 setTimeout,这些参数将提供给回调函数。这摆脱了令人讨厌的绑定(bind):

doSeparated();

function doSeparated() {
    var message = "Goodbye";
    setTimeout(outer, 3000, message);
}

function outer(message) {
    alert(message);
}

请注意,bindsetTimeout 的额外参数在旧版 IE 中均不起作用。在这种情况下,您可以使用柯里化(Currying)(在我看来,这是除了原始嵌套解决方案之外的最佳解决方案):

doSeparated();

function doSeparated() {
    var message = "Goodbye";
    setTimeout(outer(message), 3000);
}

function outer(message) {
    return function () {
        alert(message);
    };
}

除此之外,我想不出其他好的解决方案。最好的解决方案是您原来的嵌套解决方案。

<小时/>

1 函数无法访问子作用域中定义的任何变量,否则您将能够访问全局作用域中的每个变量。

关于JavaScript 闭包和回调函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29138991/

相关文章:

javascript - Node 没有从 Firebase 数据库中删除?

javascript - 我对 Java 脚本缺少什么,请帮助我?

javascript - 如何在 filter 方法中返回与 && 内部回调函数连接的 bool 值?

javascript - 如何使用 microapps Node.js 模块处理 Shopify 的 API 调用限制

ios - Swift 语法 - 闭包

java - 8 之前的 Java 版本怎么会不支持闭包呢?

javascript - JS中变量的作用域

javascript - 未捕获的语法错误 : invalid or unexpected token for Unicode line separator\u2028

javascript - 使用 Kendo Grid,你能发现列是否隐藏在 DataBound 事件中吗?

c++ - 在 C++ 中传递回调函数参数的最佳方法