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];
    };
  };
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • _.each 和 _.forEach 在 ES5 中,只能对数组对象进行迭代,而 underscore 提供的...
    金华每文阅读 578评论 0 0
  • java笔记第一天 == 和 equals ==比较的比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量...
    jmychou阅读 1,524评论 0 3
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,786评论 0 9
  • Set Set 是不包含重复值的列表。常见的Set使用场景是检查某个值是否存在. Set实例需要用new Set(...
    牙哥阅读 403评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,767评论 18 399