我得到了一个像这样的函数:
//! 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;
,即在定义时引用变量,因此要么应该是非法的,要么其行为应该是未定义的。但是,在一些浏览器上似乎可以正常工作。
更多研究和思考后,我想到了其他解决方案。
解决方案1:给匿名函数(
MyFunc
)命名,这样我就可以在内部使用它的名称 (参考这里)。代码:
var WorkFunc = function MyFunc() { // Name it MyFunc.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
MyFunc(); // Use MyFunc here
});
RecordIndex++;
}
};
WorkFunc();
- 解决方案2:使用函数声明代替函数表达式,这样更像是一个递归函数(虽然不完全相同)(参考此处)。
代码:
function WorkFunc() { // Declare function.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
WorkFunc();
});
RecordIndex++;
}
};
WorkFunc();
- 解决方案三:将变量作为参数(
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
变量本身上,而不是值,因此当函数被调用时,它获取当前值,即函数本身。 - I Hate LazyWorkOnRecord(RecordArray[RecordIndex], WorkFunc)
(或者如果参数来自于WorkOnRecord
,也可以这样做)。顺便说一句,FWIW。 - I Hate Lazy