Item 24: Use a Variable to Save a Reference to
arguments
An iterator is an object providing sequential access to a collection of
data. A typical API provides a next method that provides the next
value in the sequence. Imagine we wish to write a convenience
function that takes an arbitrary number of arguments and builds an
iterator for those values:
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // 1
it.next(); // 4
it.next(); // 1
The values function must accept any number of arguments, so we con-
struct our iterator object to iterate over the elements of the arguments
object:
function values() {
var i = 0, n = arguments.length;
return {
hasNext: function() {
return i < n;
},
next: function() {
if (i >= n) {
throw new Error("end of iteration");
}
return arguments[i++]; // wrong arguments
}
};
}
But this code is broken, which becomes clear as soon as we attempt
to use an iterator object:
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // undefined
it.next(); // undefined
it.next(); // undefined
The problem is due to the fact that a new arguments variable is implic-
itly bound in the body of each function. The arguments object we are
interested in is the one associated with the values function, but the
iterator’s next method contains its own arguments variable. So when
we return arguments[i++] , we are accessing an argument of it.next
instead of one of the arguments of values .
The solution is straightforward: Simply bind a new local variable in
the scope of the arguments object we are interested in, and make sure
that nested functions only refer to that explicitly named variable:
function values() {
var i = 0, n = arguments.length, a = arguments;
return {
hasNext: function() {
return i < n;
},
next: function() {
if (i >= n) {
throw new Error("end of iteration");
}
return a[i++];
}
};
}
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // 1
it.next(); // 4
it.next(); // 1
Things to Remember
✦ Be aware of the function nesting level when referring to arguments .
✦ Bind an explicitly scoped reference to arguments in order to refer to
it from nested functions.
来源:Effective Javascript