【发布时间】:2012-11-15 02:10:49
【问题描述】:
给我一个这样的函数:
//! Work on record.
/*!
\param[in] Record (object) Record.
\param[in] AsyncCallback (function) Asynchronous callback which is called when the operation is complete. It takes no parameters.
*/
function WorkOnRecord(Record, AsyncCallback)
{
/* Work on Record asynchronously (e.g. by calling $.ajax())
and call AsyncCallback on complete. */
}
现在,我有一个对象数组 (RecordArray),我需要将它们一个一个地提供给上述函数,这意味着我必须等到它回调后再调用它。
所以我想出了:
$(function() {
var RecordArray = SomeOtherFunc(); // RecordArray is an array of objects.
// Work on records, one by one.
var RecordIndex = 0;
var WorkFunc = function() {
// If there are still records to work on...
if(RecordIndex < RecordArray.length)
{
// Work on record.
WorkOnRecord(RecordArray[RecordIndex], function() {
// Move forward to next record.
WorkFunc();
});
RecordIndex++;
}
// If there are no more records to work on...
else
{
/* We are all done. */
}
};
WorkFunc(); // Start working.
});
如您所见,WorkFunc 实际上是从定义了变量WorkFunc 的匿名函数内部调用的。 这在 ECMAScript/Javascript 中是否合法? (法律意味着它适用于所有符合标准的浏览器)
我的意思是,对我来说,它很像 Javascript 中的 var c = c + 1; 或 C/C++/ObjC/Java 中的 int c = c + 1;,即 在定义变量时引用变量,所以要么它应该是非法的,要么它的行为应该是未定义的。
不过,它似乎在一些浏览器上运行良好。
经过更多的研究和思考,我想出了其他解决方案。
- 解决方案一:给匿名函数命名(
MyFunc),这样我就可以在里面使用它的名字(参考here)。
代码:
var WorkFunc = function MyFunc() { // Name it MyFunc.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
MyFunc(); // Use MyFunc here
});
RecordIndex++;
}
};
WorkFunc();
- 解决方案 2:使用函数声明而不是函数表达式,这样它更像是一个递归函数(尽管不完全是)(参考 here)。
代码:
function WorkFunc() { // Declare function.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
WorkFunc();
});
RecordIndex++;
}
};
WorkFunc();
- 解决方案3:将变量作为参数传递(
NextStepFunc),这样我就不需要在里面引用WorkFunc(这看起来很有趣)。
代码:
var WorkFunc = function(NextStepFunc) { // Accept function as parameter.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
NextStepFunc(NextStepFunc); // Call function as defined by parameter.
});
RecordIndex++;
}
};
WorkFunc(WorkFunc); // Pass function as variable to parameter.
但我的问题仍然存在:我原来的解决方案合法吗?
【问题讨论】:
-
是的,这是合法的。该函数关闭了
WorkFunc变量本身,而不是值,因此在调用该函数时,它会获取当前值,即该函数。 -
我只是担心这里的回调地狱......但我更喜欢解决方案。
-
FWIW,如果你没有传递任何参数,你可以使用
WorkOnRecord(RecordArray[RecordIndex], WorkFunc)(或者如果参数来自WorkOnRecord,你也可以这样做)。 -
如前所述,以原始方式进行操作没有问题。解决方案 2 与您的原始解决方案几乎相同 - 存在一些差异太复杂而无法在评论中解释,但无论如何它们对于这种情况都无关紧要。 (看看this。)
标签: javascript anonymous-function self-reference variable-declaration function-expression