简体   繁体   English

JavaScript闭包和回调函数

[英]JavaScript closures & callback functions

Can someone clarify this point for me? 有人可以为我澄清这一点吗?

Two of my favourite features in JavaScript are closures and the fact that functions are first class objects. 我在JavaScript中最喜欢的两个功能是闭包和函数是一流对象的事实。

If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function. 如果我想利用回调函数中的闭包功能,那么该函数必须始终是内部函数。 For example: 例如:

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

There is no way I can pass a parameter to an outer callback function. 我无法将参数传递给外部回调函数。 For example: 例如:

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

This doesn't work, of course. 当然,这不起作用。

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? 问题是,除了将它们添加到参数列表之外,还有什么方法可以将内部变量传递给这样的外部函数?

Thanks 谢谢

If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function. 如果我想利用回调函数中的闭包功能,那么该函数必须始终是内部函数。

That's correct. 没错 Every function in JavaScript only has access those variables which are either defined in its own scope or defined in a parent scope 1 . JavaScript中的每个函数都只能访问那些在其自己的作用域中定义或在父作用域1中定义的变量。 Therefore, your first example works while your second example doesn't. 因此,第一个示例有效,而第二个示例无效。

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? 问题是,除了将它们添加到参数列表之外,还有什么方法可以将内部变量传递给这样的外部函数?

No, there's no way to do that. 不,没有办法。 Well, technically you could add your inner variable to an object and then bind that object to the external function after which you can access the inner variable from the this context of the external function, but that is no better than passing the variable to the function directly. 嗯,从技术上讲,您可以将内部变量添加到对象,然后将该对象bind到外部函数,之后您可以从外部函数的this上下文访问内部变量,但这并不比将变量传递给函数更好直。

 doSeparated(); function doSeparated() { var message = "Goodbye"; setTimeout(outer.bind({ message: message }), 3000); } function outer() { alert(this.message); } 

Since you are using setTimeout , you can pass extra arguments to setTimeout which will be given to the callback function. 由于您正在使用setTimeout ,因此可以将额外的参数传递给setTimeout ,该参数将提供给回调函数。 This gets rid of the nasty bind : 这摆脱了讨厌的bind

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

Note that both bind and extra arguments of setTimeout don't work in older versions of IE. 请注意, setTimeout bind和额外参数在旧版本的IE中均不起作用。 In that case, you can use currying instead (which in my humble opinion is the best solution aside from your original nested solution): 在这种情况下,您可以改用curring(在我看来,这是除原始嵌套解决方案之外的最佳解决方案):

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

Other than these, there's no other good solution that I can think of. 除此之外,没有其他我可以想到的好的解决方案。 The best solution is your original nested solution. 最好的解决方案是您原始的嵌套解决方案。


1 A function doesn't have access to any variable defined in a child scope or else you would be able to access every variable from the global scope. 1函数无权访问子作用域中定义的任何变量,否则您将可以访问全局作用域中的每个变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM