This is what I saw when reading the source code of underscore (1.3.3). Its each method
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 (iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
for (var key in obj) {
if (_.has(obj, key)) {
if (iterator.call(context, obj[key], key, obj) === breaker) return;
}
}
}
};
There is a sentence in this method
if (obj.length === obj.length)
I didn’t understand it after looking at it for a long time. After being pointed out by an expert, this sentence is equivalent to
if (typeof obj.length === 'number')
is used to determine whether the element is of numeric type. typeof and Object.prototype.toString are common ways of writing. The last one is uncommon and difficult for ordinary people to understand.
Some libraries have tool functions for type judgment, such as
function isNumber1(a){
return typeof a === 'number'
}
Or use Object.prototype.toString
function isNumber2(a) {
return Object.prototype.toString.call(a ) === '[object Number]'
}
Changed to this way
function isNumber3(a){
return a === a
}
Test with various types
var arr = ['1', true, false, undefined, null, {}, [], 1]
for (var i=0; i
console.log(isNumber3(arr[i]))
}
As a result, only the last item in the array is true. That is, only numeric type a === a is true.
Why not use typeof, because string comparison theoretically needs to traverse all characters, and the performance is directly proportional to the length of the string.