Reputation: 9332
var timers = { //#1
timerID: 0, //#2
timers: [], //#2
add: function(fn) { //#3
this.timers.push(fn);
},
start: function runNext() { //#4
if (this.timerID) return;
(function() {
if (timers.timers.length > 0) {
for (var i = 0; i < timers.timers.length; i++) {
if (timers.timers[i]() === false) {
timers.timers.splice(i,1);
i--;
}
}
timers.timerID = setTimeout(runNext, 0);
}
})();
},
The code above is from Secrets of the JavaScript Ninja by John Resig. the part I don't understand is where he assigns a function to the property of start
and then names that function runNext
. Can someone please offer some clarification?
Upvotes: 3
Views: 114
Reputation: 7719
The "name" of a function also serves a special role which is particularly useful when used in a FunctionExpression1:
x = function theFunc (z) {
// theFunc is in scope here, and so can be used to refer
// to the function itself in a recursive manner
// (in the posted code it is used with setTimeout)
return z > 0 ? theFunc(z - 1) * z : 1;
};
// theFunc is NOT in scope here in valid ECMAScript; IE quirks anyone?
Unlike x
, theFunc
above will always refer to the particular function-object. Without this name an additional closure (or use of this
plumbing) would be required to access the function recursively. Also, the tight binding makes theFunc
independent of the current this
binding, which may be good or bad - note that after the call to setTimeout
, theFunc
will be called in a different binding context (which also makes the use of this.timerID
suspect).
In ECMAScript 3rd edition, then function name (Identifier) and arguments.callee would evaluate to the same function-object inside the scope. However, arguments.callee is invalid per ECMAScript 5th edition "strict" mode.
The name may also show up in stack-traces, toString()
and name
/displayName
(as implemented).
1From ES5 Annotated, Function Declarations:
The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively ..
Upvotes: 2
Reputation: 3751
In JavaScript, everything is an object with members, and those members can serve as properties or methods according to what you put in them.
In this case, timer
will have some members that will be used as methods (add
and start
). In order to do that, they will contain references to function
code. The only reason he gives a name to the code reference in start
(runNext
), is so he can recursively call that function again from inside. The second function reference you see inside runNext
, is another anonymous function reference that is not even being assigned to anything, but it's just there to make it return something at that moment for runNext
.
Upvotes: -1