5

JavaScript调用这样的东西有什么区别:

var reader = new FileReader();

reader.onload = (function (theFile) {
    return function (e) {
        loadData(e.target.result); 
    };
})(file);

reader.readAsText(file);

和(结果在 loadData 函数中是一样的):

var reader = new FileReader();

reader.onload = function(e) {
    loadData(e.target.result);
}; 

reader.readAsText(file);

到目前为止,我一直将 JavaScript 用于简单的任务(输入验证、简单的 ajax 调用),但现在我需要更深入的了解......

4

2 回答 2

2

在您的特定情况下没有区别(请注意,您的第一个片段中的函数是使用参数调用的file,但由于您忽略它,它不应该有任何副作用)。但是,请看以下示例:

var reader = new FileReader();

var my_temporary_var = 42;

reader.onload = function(e){
    loadData(e.target.result, my_temporary_var);
}

到目前为止,一切都是一样的。但是,如果您进行更改my_temporary_var,它也会在您的匿名函数内部进行更改。为了防止这种情况,您创建了一个闭包:

reader.onload = (function(some_value) {
    return function(e){
        loadData(e.target.result, some_value);
    };
})(my_temporary_var);

你创建一个匿名函数,它接受你想要绑定到另一个函数的参数,然后立即调用这个函数。请注意,依赖my_temporary_var已解决。

其他示例

有些人喜欢在 for 循环中创建许多函数:

var i;
for(i = 0; i < myObjects.length; ++i)
    myObjects[i].onload = function(e) { myObjects[i].doSomething(); };

让我们假设myObjects[0].onload将首先处理,但for 循环之后。给定的处理程序function(e) { myObjects[i].doSomething(); };使用 object myObjects[i]。但是,i == myObjects.length: 我们访问了一个甚至不存在的对象!由于我们尝试访问该函数的属性,我们将得到一个异常并且脚本将停止。

发生这种情况是因为i在匿名函数中是一个引用,而不是用作值。为了防止这种情况,您必须使用闭包:

var i;
for(i = 0; i < myObjects.length; ++i)
    myObjects[i].onload = (function(index){
        return function(e) { myObjects[index].doSomething(); };
    })(i);
于 2012-10-29T11:52:09.387 回答
1

它与以下示例非常相似:

var fruit = "Apple";

var fruit = (function(X) {
    return "Apple";
})(1);

您只需将分配封闭在一个闭包中,在上述情况下,这根本没有任何作用。但如果你这样做:

var fruit_names = ["Pear", "Apple"];
var fruits = [];
for (x in fruits) {
    fruits.push({
        getName: (function(fruit_id) {
            return fruits[fruit_id];
        })(x)
    });
}

您刚刚创建了一个对象数组,它们都具有该函数,它们从数组getName中返回它们自己的名称。fruit_names这种对闭包的使用可以创建非常灵活的结​​构,因为在这个示例中,您可以通过更改fruit_names数组来更改水果对象的名称,该数组用作对象的配置接口。

于 2012-10-29T12:02:37.867 回答