Che*_*tan 33 javascript scope function callback
我正在使用XMLHttpRequest,我想在成功回调函数中访问本地变量.
这是代码:
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();
}
Run Code Online (Sandbox Code Playgroud)
我想这样称呼它:
var test = "lol";
getFileContents("hello.js", function(data) {
alert(test);
});
Run Code Online (Sandbox Code Playgroud)
这里test将超出回调函数的范围,因为只有封闭函数的变量可以在回调函数中访问.传递test给回调函数的最佳方法是什么,以便正确alert(test);显示test?
编辑:
现在,如果我有以下代码调用上面定义的函数:
for (var test in testers) {
getFileContents("hello.js", function(data) {
alert(test);
});
}
Run Code Online (Sandbox Code Playgroud)
该alert(test);代码只打印的最后一个值test从for环.如何使它打印出调用test函数时的值getFileContents?(我想这样做而不改变,getFileContents因为它是一个非常通用的辅助函数,我不想通过传递一个特定的变量test来使它具体化.
gna*_*arf 41
您提供的代码test仍将在回调范围内. xhr不会,比其他xhr.responseText被传递进来data.
从评论更新:
假设你的代码看起来像这样:
for (var test in testers)
getFileContents("hello"+test+".js", function(data) {
alert(test);
});
}
Run Code Online (Sandbox Code Playgroud)
当此脚本运行时,test将分配键的值testers- getFileContents每次调用,在后台启动请求.当请求完成时,它会调用回调. 将从循环中test包含FINAL VALUE,因为该循环已经完成执行.
你可以使用一种称为闭包的技术来解决这类问题.您可以创建一个返回回调函数的函数,创建一个可以保存到变量的新范围:
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
);
}
Run Code Online (Sandbox Code Playgroud)
这基本上会创建一个新的范围(以及我们的新功能),它将"保持"其价值test.
编写同类事物的另一种方式:
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`
}
Run Code Online (Sandbox Code Playgroud)
JavaScript使用词法作用域,这基本上意味着您的第二个代码示例将像您打算如何工作一样工作.
考虑以下示例,借用David Flanagan的权威指南1:
var x = "global";
function f() {
var x = "local";
function g() { alert(x); }
g();
}
f(); // Calling this function displays "local"
Run Code Online (Sandbox Code Playgroud)
还要记住,与C,C++和Java不同,JavaScript没有块级范围.
此外,您可能还有兴趣查看以下文章,我强烈推荐:
1 David Flanagan:JavaScript - The Definitive Guide,Fourth Edition,Page 48.