Question about the implementation of the "each" function I found in the underscore.js source code (source below).
First, could someone explain what the line "else if (obj.length === +obj.length) " is checking for.
Second, could someone explain why hasOwnProperty.call(obj, key) is used, as opposed to obj.hasOwnProperty? Is it because the passed in obj may not implement hasOwnProperty (which I thought every javascript object did)
any insights appreciated. Thanks.
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
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, l = obj.length; i < l; i++) {
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) {
if (iterator.call(context, obj[key], key, obj) === breaker) return;
}
}
}
};
This:
+obj.length
...will do a toNumber conversion on the value of length
.
It appears as though they're making sure that length
references a number by doing the toNumber conversion, and verifying that it's still the same number after the conversion.
If so, they assume that it is an Array, or at least an Array-like object for iteration.
If not, they assume that enumeration of all key value pairs is desired.
var obj = {
length:null,
someprop:'some value'
};
obj.length === +obj.length; // false, so do the enumeration
var obj = {
length: 2,
"0":'some value',
"1":'some other value'
};
obj.length === +obj.length; // true, not an actual Array,
// but iteration is still probably wanted
Of course you could have an object with a length
property that is a primitive number, but still intend to enumerate the properties.
var obj = {
length: 2,
"prop1":'some value',
"prop2":'some other value'
};
obj.length === +obj.length; // true, it will iterate, but it would
// seem that enumeration is intended
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With