3

我被赋予了这样的功能:

//! 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 中合法吗?(法律意味着它适用于所有符合标准的浏览器)

我的意思是,对我来说,它很像var c = c + 1;JavascriptC/C++/ObjC/Java中,它int c = c + 1;定义变量时引用了一个变量,所以要么它应该是非法的,要么它的行为应该是 undefined

但是,它似乎在一些浏览器上运行良好。


经过更多的研究和思考,我想出了其他解决方案。

  • 解决方案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();
  • 解决方案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.

但我的问题仍然存在:我原来的解决方案合法吗?

4

1 回答 1

1

是的。匿名函数可以访问在父作用域中声明的每个变量,而不管它们的值(这是使用匿名函数进行递归的标准方法)。

请注意,如果稍后在父作用域中将变量设置为 null,则匿名函数中的后续调用将引发 TypeError(因为 null 将不再可调用)。这也意味着您甚至可以更改其值以针对另一个函数(但这绝对不是一个好习惯)。

于 2012-11-15T02:42:06.553 回答