简体   繁体   English

Javascript:如何在回调函数中访问局部变量?

[英]Javascript: How to access local variable in callback function?

I have a formidable form which parse the request. 我有一个强大的形式来解析请求。 Then along with this request is the file being uploaded.. In formidable you can listen to an event if there's a file. 然后,随着该请求一起上传文件。在强大的过程中,如果有文件,您可以收听事件。

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

This is where I will listen to the event 我将在这里聆听活动

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;
  ....
}

My first code was a chain of callback functions and it's kind of hard to read and maintain so I switch with this approach where I would declare functions then call it as a callback instead of like this: 我的第一个代码是一连串的回调函数,很难读取和维护,因此我使用这种方法进行切换,在该方法中我将声明函数,然后将其称为回调,而不是像这样:

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

With this kind of approach, I could access the outside variable which is file . 通过这种方法,我可以访问外部变量file I'm wondering what is the difference between the two in accessing the outside variables. 我想知道两者在访问外部变量之间有什么区别。 Thanks in advance. 提前致谢。

It's a matter of scope . 这是范围的问题 Code has access to the variables declared within the function, its containing function (if any), its containing function (if any), and so on, and then globals. 代码可以访问在函数中声明的变量,其包含的函数(如果有的话),其包含的函数(如果有的话)等等,然后是全局变量。

In your first example, readFileCallback is declared outside the form.on callback, and so it doesn't have access to things inside the form.on callback. 在第一个示例中, readFileCallback是在form.on回调之外声明的,因此它无法访问form.on回调内部的form.on

In your second example, the function is inside the form.on callback, and so it does have access to the things inside it. 在第二个示例中,该函数位于 form.on回调内部 ,因此它确实有权访问其中的内容。

Note that in the second example, in theory a new function is created each time the callback is called. 请注意,在第二个示例中,理论上每次调用回调时都会创建一个新函数。 That's fine, JavaScript engines are really fast at creating functions (and good ones will reuse the code even though a separate function object is created). 很好,JavaScript引擎确实可以很快地创建函数(即使创建了单独的函数对象,好的引擎也可以重用代码)。

Normally you want to create the function at the outermost location where it has access to everything it needs. 通常,您希望在最外部的位置创建该函数,在该函数中可以访问所需的所有内容。 So in your case, that would be inside form.on , but outside the readFile callback. 因此,在您的情况下,它将位于 form.on ,但位于 readFile回调之外 Which is exactly where your second example has it. 您的第二个示例正是在哪里。 But you can use a named function like your first example if you like, just put it in form.on 's callback: 但是,如果愿意,您可以像第一个示例一样使用命名函数,只需将其放在 form.on的回调中:

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

Let's take an example where everything had a simple name, and follow through two calls: 让我们举一个例子,其中所有的东西都有一个简单的名称,然后执行两次调用:

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

outer contains middle which contains inner , and outer calls middle (and middle calls inner ). outer包含middle含有innerouter的呼叫middle (和middle调用inner )。 A call: 一个电话:

outer("Test1");
  1. outer gets the arg "Test1" outer获取arg "Test1"
  2. It calls middle with "TEST1" 它用"TEST1"调用middle
  3. It calls inner with "test1" 它用"test1"调用inner
  4. inner outputs: inner输出:

    \ninnerArg = test1 innerArg = test1\nmiddleArg = TEST1 middleArg = TEST1\nouterArg = Test1 outsideArg = Test1\n

So far, so simple, but it's more exciting than that: What if middle returns a function that calls inner , instead of calling it immediately, and outer returns returns middle 's return value? 到目前为止,如此简单,但是比这更令人兴奋:如果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());          // ***
}

Now, calling outer doesn't have any output at all: 现在,调用outer根本没有任何输出:

var f = outer("Test2");

But then calling the function middle returned ( caller ) does: 但是然后调用返回的middle函数( caller )可以:

f();

Output: 输出:

innerArg = test2
middleArg = TEST2
outerArg = Test2

The arguments still exist after outer and middle return! outermiddle返回之后,参数仍然存在! But it's even more interesting: 但这更有趣:

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

Output: 输出:

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

So that means, two outerArg s still existed after both calls to outer had finished, along with two middleArgs . 因此,这意味着, outerArg还在两个电话后,存在于outer吃完后,有两个一起middleArgs How? 怎么样?

They exist on objects attached to the functions: 它们存在于附加到功能的对象上:

  • Calling outer creates an execution context (an object), which amongst other things (and leaving out a lot of details) holds the arguments and local variables for that call to outer . 呼叫outer创建一个执行上下文 (对象),其中除其他事项外(并留下了大量的细节)持有的参数和局部变量为呼叫outer Let's call it the "outer context." 我们称其为“外部上下文”。 It also has a reference to the execution context containing it (the global context, in our code). 它还引用了包含它的执行上下文(在我们的代码中为全局上下文)。 Normally that object gets cleaned up when a functon returns... 通常,当功能返回时,该对象会被清理...
  • ...but outer creates a function, middle . ...但是outer创建一个函数, middle When you create a function, the current execution context is attached to the function. 创建函数时,当前执行上下文将附加到该函数。 That's how it has access to the variables and such in that outer context. 这样便可以在外部环境中访问变量等。
  • outer calls middle , creating an inner execution context, and middle creates two other function ( inner and caller ), which each get that inner context attached to them. outer调用middle ,创建一个内部执行上下文,并且middle创建另外两个函数( innercaller ),每个函数都将内部上下文附加到它们。 middle then returns caller , so caller exists after the call to middle completes. middle然后返回 caller ,因此对middle的调用完成后,该调用caller存在。 Since caller has a reference to the inner execution context, the context continues to exist (just like any other object), even though middle has returned. 由于caller具有对内部执行上下文的引用,因此即使middle对象已返回,该上下文也仍然存在(就像其他任何对象一样)。 Since that context has a reference to inner , inner also continues to exist. 由于该上下文引用了inner ,所以inner 也将继续存在。
  • outer returns the return value of middle (which is caller ), and so that means caller still exists when outer returns, which means the inner context it refers to still exists, which means inner still exists, and the outer context still exists because the inner context has a reference to it. outer返回middle值的返回值(即caller ),这意味着当outer返回时caller仍然存在,这意味着它所引用的内部上下文仍然存在,这意味着inner仍然存在, 并且外部上下文仍然存在,因为内部上下文对此有参考。

...which is how f1 and f2 have access to those arguments after outer returns: When you run them, they look up the values in the contexts attached to them. ...这是f1f2outer返回之后如何访问这些参数的方法:运行它们时,它们将在附加到它们的上下文中查找值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM