如何构造javascript回调以便正确维护函数范围 [英] How to structure javascript callback so that function scope is maintained properly
问题描述
我正在使用 XMLHttpRequest,并且我想访问成功回调函数中的局部变量.
I'm using XMLHttpRequest, and I want to access a local variable in the success callback function.
代码如下:
function getFileContents(filePath, callbackFn) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callbackFn(xhr.responseText);
}
}
xhr.open("GET", chrome.extension.getURL(filePath), true);
xhr.send();
}
我想这样称呼它:
var test = "lol";
getFileContents("hello.js", function(data) {
alert(test);
});
在这里,test
将超出回调函数的范围,因为只有封闭函数的变量在回调函数内是可访问的.将 test
传递给回调函数以便 alert(test);
正确显示 test
的最佳方法是什么?
Here, test
would be out of the scope of the callback function, since only the enclosing function's variables are accessible inside the callback function. What is the best way to pass test
to the callback function so the alert(test);
will display test
correctly?
现在,如果我有以下代码调用上面定义的函数:
Now, if I have the following code calling the function defined above:
for (var test in testers) {
getFileContents("hello.js", function(data) {
alert(test);
});
}
alert(test);
代码只打印 for
循环中 test
的最后一个值.如何使它在调用函数 getFileContents
期间打印 test
的值?(我想在不更改 getFileContents
的情况下执行此操作,因为它是一个非常通用的辅助函数,我不想通过将诸如 test
之类的特定变量传递给它来使其特定.
The alert(test);
code only prints the last value of test
from the for
loop. How do I make it so that it prints the value of test
during the time at which the function getFileContents
was called? (I would like to do this without changing getFileContents
because it's a very general helper function and I don't want to make it specific by passing a specific variable like test
to it.
推荐答案
使用您提供的代码 test
仍将在回调的范围内.xhr
不会,除了 xhr.responseText
作为 data
传入.
With the code you have provided test
will still be in scope inside the callback. xhr
will not be, other than xhr.responseText
being passed in as data
.
从评论更新:
假设您的代码如下所示:
Assuming your code looks something like this:
for (var test in testers)
getFileContents("hello"+test+".js", function(data) {
alert(test);
});
}
当这个脚本运行时,test
将被分配到 testers
中键的值 - getFileContents
每次被调用,这会启动一个在后台请求.当请求完成时,它调用回调.test
将包含循环中的 FINAL VALUE,因为该循环已经完成执行.
As this script runs, test
will be assigned the values of the keys in testers
- getFileContents
is called each time, which starts a request in the background. As the request finishes, it calls the callback. test
is going to contain the FINAL VALUE from the loop, as that loop has already finished executing.
您可以使用一种称为闭包的技术来解决此类问题.您可以创建一个返回回调函数的函数,创建一个可以保留变量的新范围:
There is a technique you can use called a closure that will fix this sort of problem. You can create a function that returns your callback function, creating a new scope you can hold onto your variables with:
for (var test in testers) {
getFileContents("hello"+test+".js",
(function(test) { // lets create a function who has a single argument "test"
// inside this function test will refer to the functions argument
return function(data) {
// test still refers to the closure functions argument
alert(test);
};
})(test) // immediately call the closure with the current value of test
);
}
这基本上会创建一个新的作用域(连同我们的新函数),它将保持"test
的值.
This will basically create a new scope (along with our new function) that will "hold on" to the value of test
.
另一种写同样东西的方式:
Another way of writing the same sort of thing:
for (var test in testers) {
(function(test) { // lets create a function who has a single argument "test"
// inside this function test will refer to the functions argument
// not the var test from the loop above
getFileContents("hello"+test+".js", function(data) {
// test still refers to the closure functions argument
alert(test);
});
})(test); // immediately call the closure with the value of `test` from `testers`
}
这篇关于如何构造javascript回调以便正确维护函数范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!