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);

私はこれまで単純なタスク(入力検証、単純なajax呼び出し)にJavaScriptを使用していましたが、今ではもっと深い理解が必要です...

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(); };はオブジェクトを使用します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 に答える