在调用类似这样的东西时,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调用),但现在我需要更深层次的未来......
答案 0 :(得分: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(); };
使用对象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);
答案 1 :(得分: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
数组来更改水果对象的名称,该数组用作对象的配置界面。