【问题标题】:JavaScript closures & callback functionsJavaScript 闭包和回调函数
【发布时间】:2015-05-22 05:41:02
【问题描述】:

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

我最喜欢的两个 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);
}

这当然行不通。

问题是,有没有办法像这样将内部变量传递给外部函数,而不是将它们添加到参数列表中?

谢谢

【问题讨论】:

  • 将数据作为参数传递给函数是很常见的。

标签: javascript callback closures


【解决方案1】:

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

没错。 JavaScript 中的每个函数只能访问那些定义在自己的范围内或定义在父范围内的变量1。因此,您的第一个示例有效,而您的第二个示例无效。

问题是,有没有办法像这样将内部变量传递给外部函数,而不是将它们添加到参数列表中?

不,没有办法做到这一点。好吧,从技术上讲,您可以将内部变量添加到一个对象,然后将 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 中都不起作用。在这种情况下,您可以改用柯里化(在我看来,这是除了原始嵌套解决方案之外的最佳解决方案):

doSeparated();

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

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

除了这些,我想不出其他好的解决方案。最好的解决方案是您原来的嵌套解决方案。


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2013-01-18
    • 2016-07-28
    • 2016-06-16
    • 2015-12-03
    • 2010-09-19
    相关资源
    最近更新 更多