次のような関数が与えられます。
//! 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. */
}
これで、上記の関数に 1 つずつフィードする必要があるオブジェクトの配列 ( 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
れている無名関数内から実際に呼び出されます。これは ECMAScript/Javascript で合法ですか? (標準に準拠したすべてのブラウザで動作するという法的意味)WorkFunc
つまり、私にとっては、 JavascriptやC/C++/ObjC/Javaとほとんど同じvar c = c + 1;
で、定義中に変数を参照しているため、違法であるか、動作が undefined である必要があります。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
解決策 3: 内部を参照する必要がないように、変数をパラメーター ( ) として渡します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.
しかし、私の質問はまだ残っています: 私の元の解決策は合法でしたか?