each方法原码
_.each = _.forEach = function(obj, iteratee, context) {
//optimizeCb 上下文绑定,内部使用call方法
iteratee = optimizeCb(iteratee, context);
var i, length;
if (isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
isArrayLike方法:(类数组也包含数组)
function(collection) {
//本质仍是obj.length,内部做了预防obj为null的处理,obj==null?void 0:obj[key],这里使用==不严格等于,因为null==undefined为true,所以也处理了undefined的情况
var length = getLength(collection);
//MAX_ARRAY_INDEX = Math.pow(2, 53) - 1
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
//旧版本的underscore使用了如下判断,+操作符将length转换为数字,===确保length不为NaN,因为NaN===NaN为false:
length === +length
isArray方法:
//ES6
Array.isArray()
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
_.keys方法:
//keys方法返回由对象object的key组成的数组
_.keys = function(obj) {
if (!_.isObject(obj)) return [];
//nativeKeys即Object.keys,返回一个由给定对象的自身可枚举属性组成的数组,其顺序与for-in相同
if (nativeKeys) return nativeKeys(obj);
var keys = [];
//has方法,判断给定的属性是否在对象本身上
for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
_.has方法:
_.has = function(obj, path) {
if (!_.isArray(path)) {
return obj != null && hasOwnProperty.call(obj, path);
}
//无法理解这种path是数组的情况
var length = path.length;
for (var i = 0; i < length; i++) {
var key = path[i];
if (obj == null || !hasOwnProperty.call(obj, key)) {
return false;
}
obj = obj[key];
}
return !!length;
};
判断一个属性是否属于对象本身:
- hasOwnProperty()
-
propertyIsEnumerable()返回一个bool值表示属性是否可以被枚举,在原型链上的除外
-
Object.getOwnPropertyNames()返回一个由对象自身属性组成的数组(包括不可枚举属性)
网友评论