2016-09-24 9 views
0

私は要求を解析するformidableフォームを持っています。その後、このリクエストとともにファイルがアップロードされます。formidableには、ファイルがある場合にイベントを聴くことができます。Javascript:コールバック関数でローカル変数にアクセスするには?

var form = new formidable.IncomingForm({ 
    uploadDir: __dirname + '/temp', 
    keepExtensions: true 
}); 

私はイベントに耳を傾けるだろうここでは私の最初のコードは、コールバック関数の連鎖だった、それは私がどここのアプローチに切り替えて読み、維持するために、ハードのようなものだ

form.on('file', function(name, file){ 
    var file = file; 
    fs.readFile(file.path, readFileCallback); 
}); 

function readFileCallback(err, contents){ 
    console.log(file); 
    if (err) throw err; 
    .... 
} 

です私は外にアクセスすることができ、この種のアプローチで

form.on('file', function(name, file){ 
    fs.readFile(file.path, function(err, contents){ 
     console.log(file); 
     if (err) throw err; 
     .... 
    }); 
}); 

:私の代わりにこのようにコールバックとして、それを呼び出して関数を宣言するだろう変数はfileです。私は外部変数にアクセスする際に2つの違いが何であるか疑問に思っています。前もって感謝します。

+0

最初は親関数のスコープ内で定義されているので、関数を囲む関数のローカル変数にアクセスできます。 2番目は外に定義され、囲まれていません。 – gurvinder372

+0

密接に関連しています:[* JavaScriptのクロージャはどのように機能しますか?*](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) –

答えて

1

の範囲です。です。コードは、関数内で宣言された変数、関数を含む関数、関数を含む関数、およびグローバルにアクセスできます。

最初の例では、readFileCallbackform.onコールバックの外で宣言されているため、form.onコールバック内のものにアクセスすることはできません。

2番目の例では、関数はform.onコールバック内にあり、その内部のものにアクセスできます。

第2の例では、理論上、コールバックが呼び出されるたびに新しい関数が作成されることに注意してください。 JavaScriptエンジンはという非常に高速で、作成機能ではと非常に高速です(別の関数オブジェクトが作成されても、コードは再利用されます)。

通常、必要なすべてにアクセスできる最も外側の場所に関数を作成します。あなたの場合、form.onですが、以外はreadFileコールバックです。あなたの2番目の例がそれを持っている場所です。

form.on('file', function(name, file){ 
    fs.readFile(file.path, readFileCallback); 
    function readFileCallback(err, contents){ 
     console.log(file); 
     if (err) throw err; 
     .... 
    } 
}); 

は、のすべてが単純な名前を持っていた例を見てみましょう、との二つの呼び出しフォロースルー:あなたが好きしかし、もしあなただけform.onのコールバックでをそれを置く、あなたの最初の例のような名前の関数を使用することができます。

function outer(outerArg) { 
    function middle(middleArg) { 
     function inner(innerArg) { 
      console.log("innerArg = " + innerArg); 
      console.log("middleArg = " + middleArg); 
      console.log("outerArg = " + outerArg); 
     } 

     inner(middleArg.toLowerCase()); 
    } 

    middle(outerArg.toUpperCase()); 
} 

outerinnerを含むmiddleを含み、outerコールmiddle(及びmiddleコールinner)。コール:

 
innerArg = test1 
middleArg = TEST1 
outerArg = Test1 

outer("Test1"); 
  1. outerは、それがinner"test1"
  2. inner出力を呼び出し"TEST1"

  3. middleを呼び出し、引数"Test1"
  4. を取得します10

これまでのところ、そう単純で、それはそれよりももっとエキサイティングだ:middleではなく、すぐにそれを呼び出す、innerを呼び出す関数を返し、outer戻ったらどうmiddleの戻り値を返しますか?

function outer(outerArg) { 
    function middle(middleArg) { 
     function inner(innerArg) { 
      console.log("innerArg = " + innerArg); 
      console.log("middleArg = " + middleArg); 
      console.log("outerArg = " + outerArg); 
     } 
     function caller() {       // *** 
      inner(middleArg.toLowerCase());   // *** 
     }           // *** 
     return caller;        // *** 
    } 

    return middle(outerArg.toUpperCase());   // *** 
} 

さて、outer呼び出しはまったくの出力を持っていない:

var f = outer("Test2"); 

をしかし、その後middleが返される関数(caller)を呼び出す行います

f(); 

出力:

 
innerArg = test2 
middleArg = TEST2 
outerArg = Test2 

引数はまだありませんoutermiddleリターン!それがさらに興味深いのだが:

var f1 = outer("Test3"); 
var f2 = outer("Test4"); 
f2(); // Note -- calling the second one first 
f1(); 

は出力:

 
innerArg = test4 
middleArg = TEST4 
outerArg = Test4 
innerArg = test3 
middleArg = TEST3 
outerArg = Test3 

手段だからouterに両方の呼び出しが middleArgsとともに、完成した後、 outerArg sがまだ存在していました。どうやって?

彼らは機能に付属するオブジェクト上に存在し

  • outerを呼び出すと、引数とローカルを保持している他のものの中で(と詳細の多くを残して)実行コンテキスト(オブジェクト)を作成しますその呼び出しの変数はouterです。それを「外部のコンテキスト」と呼ぶことにしましょう。また、それを含む実行コンテキスト(コード内のグローバルコンテキスト)への参照もあります。ファンクションが返ってくると、通常そのオブジェクトはクリーンアップされます。
  • ...しかし、outerは、関数middleを作成します。関数を作成すると、現在の実行コンテキストが関数に付加されます。それは、それが外部の文脈で変数などにアクセスする方法です。
  • outerは、内側実行コンテキストを作成、middleを呼び出し、middleは、それぞれ、内側コンテキストがそれらに付着していること得る他の二つの機能(innercaller)を作成します。middle次にcallerを返すので、middleの呼び出しが完了した後にcallerが存在します。 callerには内部実行コンテキストへの参照があるため、middleが返されても、コンテキストは他のオブジェクトと同様に存在し続けます。そのコンテキストはinnerへの参照を持っているので、innerが存在し続けます。
  • outercallerある)middleの戻り値を返し、その結果が場合outer戻り、それはまだinnerがまだ存在を意味し、存在を指す内部コンテキストを意味し、外側コンテキストcallerがまだ存在手段内側のコンテキストには参照があるため、まだ存在しています。あなたがそれらを実行すると、彼らはそれらに添付のコンテキストで値を検索:f1f2outer戻った後、これらの引数へのアクセス権を持っているかである

...。

+0

その場合は、 'form.on'変数にアクセスするために' event'の中にある私の関数ですか? –

+0

@JMacantos:そうです。 –

+0

Aha!今私は自分の関数の外の変数を取得します。ありがとうございます。 –

関連する問題