map方法源碼
_.map = _.collect = function(obj, iteratee, context) {
//對回調(diào)函數(shù)綁定上下文
iteratee = cb(iteratee, context);
//將obj與array兩種情況巧妙的結(jié)合在一起,用&&操作符簡化寫法
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
results = Array(length);
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
cb方法
var builtinIteratee;
//argCount參數(shù)用于optimizeCb方法內(nèi)部的判斷
var cb = function(value, context, argCount) {
//不清楚為什么要判斷
if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
//對迭代器的綁定做了三種情況的判斷
//_.identity返回原值
if (value == null) return _.identity;
//是function則綁定上下文
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
//是object則會返回一個isMatch方法满俗,可以判斷兩個對象的自身屬性是否匹配
if (_.isObject(value) && !_.isArray(value)) return _.matcher(value);
//不是以上三者转捕,則
return _.property(value);
};
//iteratee方法只是cb的開放出的入口
_.iteratee = builtinIteratee = function(value, context) {
return cb(value, context, Infinity);
};
optimizeCb方法
//主要是為了避免使用arguments,優(yōu)化性能唆垃。使用call而不是apply也是出于性能優(yōu)化的考慮
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount) {
case 1: return function(value) {
return func.call(context, value);
};
// The 2-parameter case has been omitted only because no current consumers
// made use of it.
case null:
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
matcher方法
_.matcher = _.matches = function(attrs) {
//extendOwn用于copy對象自身的屬性
attrs = _.extendOwn({}, attrs);
return function(obj) {
return _.isMatch(obj, attrs);
};
};
isMatch方法
//比對兩個對象的屬性是否完全匹配
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
//確保得到一個對象
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
property方法
_.property = function(path) {
if (!_.isArray(path)) {
return shallowProperty(path);
}
return function(obj) {
return deepGet(obj, path);
};
};
deepGet
var deepGet = function(obj, path) {
var length = path.length;
for (var i = 0; i < length; i++) {
if (obj == null) return void 0;
obj = obj[path[i]];
}
//在循環(huán)中判斷在前五芝,遞增在后,所以最后return時需要判斷
return length ? obj : void 0;
};
shallowProperty
var shallowProperty = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};