如何构造javascript回调以便正确维护函数范围 [英] How to structure javascript callback so that function scope is maintained properly

查看:22
本文介绍了如何构造javascript回调以便正确维护函数范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆