map与cb等方法源码学习

map方法源码

_.map = _.collect = function(obj, iteratee, context) {
    //对回调函数绑定上下文
    iteratee = cb(iteratee, context);
    //将obj与array两种情况巧妙的结合在一起,用&&操作符简化写法
    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参数用于optimizeCb方法内部的判断
  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,优化性能。使用call而不是apply也是出于性能优化的考虑
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]];
    }
    //在循环中判断在前,递增在后,所以最后return时需要判断
    return length ? obj : void 0;
  };

shallowProperty

var shallowProperty = function(key) {
    return function(obj) {
      return obj == null ? void 0 : obj[key];
    };
  };

你可能感兴趣的:(map与cb等方法源码学习)