我有一个强大的形式来解析请求。然后,随着该请求一起上传文件。在强大的过程中,如果有文件,您可以收听事件。
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
。我想知道两者在访问外部变量之间有什么区别。提前致谢。
这是范围的问题。代码可以访问在函数中声明的变量,其包含的函数(如果有的话),其包含的函数(如果有的话)等等,然后是全局变量。
在您的第一个示例中,readFileCallback
是在form.on
回调外部声明的,因此它无权访问form.on
回调内部的内容。
在第二个例子中,该功能是里面的form.on
回调,所以它可以访问它里面的东西。
请注意,在第二个示例中,理论上每次调用回调时都会创建一个新函数。很好,JavaScript引擎确实可以很快地创建函数(即使创建了单独的函数对象,好的引擎也可以重用代码)。
通常,您想在最外部的位置创建该函数,在该函数中可以访问所需的所有内容。所以你的情况,这将是内部 form.on
的,但外面的readFile
回调。您的第二个示例正是在哪里。但是,如果愿意,您可以像第一个示例一样使用命名函数,只需将其放在 form.on
的回调中即可:
form.on('file', function(name, file){
fs.readFile(file.path, readFileCallback);
function readFileCallback(err, contents){
console.log(file);
if (err) throw err;
....
}
});
让我们举一个例子,其中所有的东西都有一个简单的名称,然后执行两次调用:
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
包含middle
其中包含inner
和outer
电话middle
(和middle
电话inner
)。一个电话:
outer("Test1");
outer
获取arg "Test1"
middle
与"TEST1"
inner
与"test1"
inner
输出:
innerArg = test1 middleArg = TEST1 externalArg = Test1
到目前为止,如此简单,但是比这更令人兴奋:如果middle
返回一个函数调用inner
,而不是立即调用它,然后outer
返回middle
return的返回值,该怎么办?
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 externalArg = Test2
参数仍然存在,outer
然后middle
返回!但这更有趣:
var f1 = outer("Test3");
var f2 = outer("Test4");
f2(); // Note -- calling the second one first
f1();
输出:
innerArg = test4 middleArg = TEST4 externalArg = Test4 innerArg = test3 middleArg = TEST3 externalArg = Test3
因此,这两个调用都结束后,仍然存在两个 outerArg
souter
和两个 middleArgs
。如何?
它们存在于附加到功能的对象上:
outer
会创建一个执行上下文(一个对象),除其他事项外(还有很多细节),该上下文包含该调用和的参数和局部变量outer
。我们称其为“外部上下文”。它还引用了包含它的执行上下文(在我们的代码中为全局上下文)。通常,当函数返回时,该对象会被清理...outer
创建一个函数,middle
。创建函数时,当前执行上下文将附加到该函数。这样便可以在外部环境中访问变量等。outer
调用middle
,创建一个内部执行上下文,并middle
创建两个其他函数(inner
和caller
),每个函数都将其附加到该内部上下文。middle
然后返回 caller
,因此caller
在调用middle
完成后存在。由于caller
具有对内部执行上下文的引用,因此即使middle
返回了上下文,该上下文仍将继续存在(就像其他任何对象一样)。由于该上下文引用inner
,因此inner
也继续存在。outer
返回middle
(是caller
)的返回值,因此,caller
当outer
返回时,意味着仍然存在,这意味着它所引用的内部上下文仍然存在,这意味着inner
仍然存在,并且外部上下文仍然存在,因为内部上下文对它的引用。......这是怎么f1
和f2
访问后这些参数outer
的回报:当您运行他们,他们查找在附属于他们的背景值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句