JavaScript 闭包和回调函数

JavaScript closures & callback functions

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

JavaScript 中我最喜欢的两个特性是闭包和函数首先是 class 个对象这一事实。

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

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 中均无效。在这种情况下,您可以改用柯里化(以我的拙见,这是除了原始嵌套解决方案之外的最佳解决方案):

doSeparated();

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

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

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


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