This question already has an answer here:
-
underscore's each checking for {} return of callback
1 answer
In underscore.js, there is code like this:
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
for example in "each" function
var each = _.each = _.forEach = function(obj, iterator, context) {
if (obj == null) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, length = obj.length; i < length; i++) {
if (iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
}
};
I don't understand, why add this if(xxx === breaker) return;
? When will iterator.call(context, obj[keys[i]], keys[i], obj) === breaker
?
From the Annotated source code,
Establish the object that gets returned to break out of a loop iteration.
It is just a sentinel value and if the iterator function returns breaker
, _.each
will return immediately. Since, breaker
is not assigned to any other object, no other object can be equal to breaker
(it is matched with ===
). It is used internally, by _.every
and _.any
.
_.every
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
_.any
if (result || (result = iterator.call(context, value, index, list))) return breaker;
These two functions return breaker
, so that _.each
will break out of the iterations.
It is used in other _underscore
helpers, like _.all()
, _.every()
, _.any()
which use the _.each()
function to loop through the collection, but return the breaker
when they wanna stop the each loop (i.e. they found the element they were looking for etc.)
If you scroll up in the code, you will see the following code:
var breaker = {};
So it is checking if the function it is calling (the iterator
) is returning an empty object. If it is, the each "loop" is broken and the function ends.