• underscore collections


    1、_.each(list, iterator, [context]):对集合中每一元素执行处理器方法.

    如果传递了context参数,则把iterator绑定到context对象上。每次调用iterator都会传递三个参数:(element, index, list)。如果list是个JavaScript对象,iterator的参数是 (value, key, list))。如果存在原生的forEach方法,Underscore就使用它代替。

    var each = _.each = _.forEach = function(obj, iterator, context) {
    	//不处理null
    	if (obj == null) return;
    	//宿主环境支持foreach,则优先调用
    	if (nativeForEach && obj.forEach === nativeForEach) {
    	  obj.forEach(iterator, context);
    	//obj.length是number,以后for循环都需要加这个条件
    	} else if (obj.length === +obj.length) {
    	  //obj为数组
    	  for (var i = 0, l = obj.length; i < l; i++) {
    	  	//i是obj的序号,iterator的返回值如果是breaker的话,则终止;breaker是内部对象,只在any中进行调用
    	    if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
    	  }
    	} else {
    	  //obj为对象
    	  for (var key in obj) {
    	  	//不考虑原型链的属性
    	    if (_.has(obj, key)) {
    	      if (iterator.call(context, obj[key], key, obj) === breaker) return;
    	    }
    	  }
    	}
    };
    

    2、_.map(list, iterator, [context]) :通过变换函数(iterator迭代器)把list中的每个值映射到一个新的数组中

    _.map = _.collect = function(obj, iterator, context) {
    	var results = [];
    	if (obj == null) return results;
    	if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    	each(obj, function(value, index, list) {
    	  //自增数组;iterator需要有返回值;
    	  results[results.length] = iterator.call(context, value, index, list);
    	});
    	//如果是数组的话,一定要返回相同长度的新数组
    	if (obj.length === +obj.length) results.length = obj.length;
    	return results;
    };
    
    var a = [1,2,3,4,5];
    var result = _.map(a, function(value){
      if(value < 3){
        return value%2 ? value:0;
      }
    })
    console.log(result);
    

    3、_.reduce():list中元素归结为一个单独的数值  

    Memo是reduce函数的初始值,reduce的每一步都需要由iterator返回。这个迭代传递4个参数:memo, value 和 迭代的index(或者 key)和最后一个引用的整个 list。

    _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    	var initial = arguments.length > 2;
    	if (obj == null) obj = [];
    	if (nativeReduce && obj.reduce === nativeReduce) {
    	  //为什么用bind,而不用call方法呢?
    	  if (context) iterator = _.bind(iterator, context);
    	  return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    	}
    	each(obj, function(value, index, list) {
    	  if (!initial) {
    	  	//如果没有memo,则把第一个值作为memo;只是考虑第一次的情况,真巧妙
    	    memo = value;
    	    initial = true;
    	  } else {
    	    memo = iterator.call(context, memo, value, index, list);
    	  }
    	});
         //TypeError:内置的js对象 if (!initial) throw new TypeError('Reduce of empty array with no initial value'); return memo; }; 

    4、_reduceRight():从右侧开始执行reduce函数

    _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
        var initial = arguments.length > 2;
        if (obj == null) obj = [];
        if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
          if (context) iterator = _.bind(iterator, context);
          return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
        }
        //函数反转
        var reversed = _.toArray(obj).reverse();
        if (context && !initial) iterator = _.bind(iterator, context);
        return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
      };
    

    5、_.find():遍历list,返回第一个通过iterator迭代器真值检测的元素值.

    如果没有值传递给测试迭代器将返回undefined。 如果找到匹配的元素,函数将立即返回,不会遍历整个list。 

      _.find = _.detect = function(obj, iterator, context) {
        var result;
      //找到一个就返回 any(obj, function(value, index, list) { if (iterator.call(context, value, index, list)) { result = value;
         //any iterator return true return true; } }); return result; };

    6、_.filter():遍历list中的每个值,返回包含所有通过iterator真值检测的元素值。如果存在原生filter方法,则用原生的filter方法。

    _.filter = _.select = function(obj, iterator, context) {
        var results = [];
        if (obj == null) return results;
        if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
        each(obj, function(value, index, list) {
          //自增函数
          if (iterator.call(context, value, index, list)) results[results.length] = value;
        });
        return results;
      };
    

    7、_.reject():返回没有用过iterator真值检测的元素值,与filter相反

    _.reject = function(obj, iterator, context) {
        var results = [];
        if (obj == null) return results;
        each(obj, function(value, index, list) {
          if (!iterator.call(context, value, index, list)) results[results.length] = value;
        });
        return results;
      };
    

    8、_.every():如果list中的所有元素都通过iterator的真值检测就返回true

    _.every = _.all = function(obj, iterator, context) {
        var result = true;
        if (obj == null) return result;
        if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
        each(obj, function(value, index, list) {
          //result = (result && iterator.call(context, value, index, list)) 太高明了
          if (!(result = result && iterator.call(context, value, index, list))) return breaker;
        });
        return !!result;
      };
    

    9、_.any(): 如果list中有任何一个元素通过 iterator 的真值检测就返回true。也叫some

    一旦找到了符合条件的元素, 就直接中断对list的遍历. 如果存在原生的some方法,就使用原生的some

    var any = _.some = _.any = function(obj, iterator, context) {
      //如果iterator存在,则继续;如果iterator不存在,则执行iterator = _.identity(默认的迭代器或处理器) iterator || (iterator = _.identity); var result = false; if (obj == null) return result; if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); each(obj, function(value, index, list) { if (result || (result = iterator.call(context, value, index, list))) return breaker; });
      //!!一般用来将后面的表达式强制转换为布尔类型的数据(boolean),也就是只能是true或者false return !!result; };

    10、_.include():集合中是否有值与目标参数完全匹配(同时将匹配数据类型)

    _.include = _.contains = function(obj, target) {
        var found = false;
        if (obj == null) return found;
        //这种return太好了
        if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
        found = any(obj, function(value) {
          return value === target;
        });
        return found;
      };
    

    11、_.invoke():在list的每个元素上执行methodName方法。 任何传递给invoke的额外参数,invoke都会在调用methodName方法的时候传递给它。

    _.invoke = function(obj, method) {
        var args = slice.call(arguments, 2);
        return _.map(obj, function(value) {
          //不需要method||value
          //method可以是对象的属性名
          return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
        });
      };
    

    12、_.pluck():获取对象数组的属性值

    _.pluck = function(obj, key) {
        return _.map(obj, function(value){ return value[key]; });
      };
    实例
    var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
    _.pluck(stooges, 'name');
    => ["moe", "larry", "curly"]
    

    13、_.max():取最大值

    14、_.min():取最小值

    _.min = function(obj, iterator, context) {
    	//iterator不存在,obj是数组,且有值
        if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
        //iterator不存在,obj为空,返回最大值
        if (!iterator && _.isEmpty(obj)) return Infinity;
        var result = {computed : Infinity};
        each(obj, function(value, index, list) {
          //iterator存在,执行iterator;不存在,computed为当前值;
          var computed = iterator ? iterator.call(context, value, index, list) : value;
          //当前计算值小于之前计算值,给result赋值;不小于的话,不赋值;把&&当if用
          computed < result.computed && (result = {value : value, computed : computed});
        });
        return result.value;
      };
    

    15、_.shuffle():随机乱序

    _.shuffle = function(obj) {
        var shuffled = [], rand;
        each(obj, function(value, index, list) {
          //随机数在0到当前已处理的数量之间
          rand = Math.floor(Math.random() * (index + 1));
          //交换随机数与当前序号的值
          shuffled[index] = shuffled[rand];
          shuffled[rand] = value;
        });
        return shuffled;
      };
    

    16、_.sortBy():返回一个排序后的list拷贝副本。
    如果有iterator参数,iterator将作为list排序的依据。迭代器也可以是字符串的属性的名称进行排序的(比如 length)。相比Array.prototype.sort,sortBy()支持对对象排序

    _.sortBy = function(obj, val, context) {
        //val是处理器,返回需要比较的值;val是对象的属性,返回属性的值
        var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
        // 调用顺序: _.pluck(_.map().sort());
        // 调用_.map()方法遍历集合, 并将集合中的元素放到value节点, 将元素中需要进行比较的数据放到criteria属性中
        // 调用sort()方法将集合中的元素按照criteria属性中的数据进行顺序排序
        // 调用pluck获取排序后的对象集合并返回
        return _.pluck(_.map(obj, function(value, index, list) {
          return {
            value : value,
            criteria : iterator.call(context, value, index, list)
          };
        }).sort(function(left, right) {
          var a = left.criteria, b = right.criteria;
          if (a === void 0) return 1;
          if (b === void 0) return -1;
          //不明白为什么这么写?
          return a < b ? -1 : a > b ? 1 : 0;
        }), 'value');
      };
    

    17、_.groupBy(list, iterator, [context])把一个集合分组为多个集合,通过 iterator 返回的结果进行分组. 

    如果 iterator 是一个字符串而不是函数, 那么将使用 iterator 作为各元素的属性名来对比进行分组.

    _.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
    => {1: [1.3], 2: [2.1, 2.4]}
    _.groupBy(['one', 'two', 'three'], 'length');
    => {3: ["one", "two"], 5: ["three"]}
    _.groupBy = function(obj, val) {
    	var result = {};
    	var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
    	each(obj, function(value, index) {
    	  var key = iterator(value, index);
    	  //|| 和 &&用得真好;如果result[key]不存在的话,赋为[];如果result[key]存在的话,给他push
    	  (result[key] || (result[key] = [])).push(value);
    	});
    	return result;
    };
    

    18、_.sortedIndex(list, value, [iterator], [context]): 使用二分查找确定value在list中的位置序号,value按此序号插入能保持list原有的排序。

    如果提供iterator函数,iterator将作为list排序的依据,包括你传递的value 。 iterator也可以是字符串的属性名用来排序(比如length)。

    _.sortedIndex([10, 20, 30, 40, 50], 35);
    => 3
    var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}];
    _.sortedIndex(stooges, {name: 'larry', age: 50}, 'age');
    => 1
    _.sortedIndex = function(array, obj, iterator) {
    	iterator || (iterator = _.identity);
    	var low = 0, high = array.length;
    	while (low < high) {
    	  //(low+high) >> 1右移一位,不是/2,因为右移的话,小数就没了
    	  var mid = (low + high) >> 1;
    	  iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    	}
    	return low;
    };
    

    19、_.toArray():转为数组

    _.toArray = function(obj) {
    	if (!obj)                                     return [];
    	if (_.isArray(obj))                           return slice.call(obj);
    	if (_.isArguments(obj))                       return slice.call(obj);
    	if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
    	// 将对象转换为数组, 数组中包含对象中所有属性的值列表(不包含对象原型链中的属性)
    	return _.values(obj);
    };
    

    20、_.size():

    _.size = function(obj) {
      //如果是对象,则返回属性的个数(不包含原型链) return _.isArray(obj) ? obj.length : _.keys(obj).length; }; 
  • 相关阅读:
    Visual Studio 起始页面关闭新闻等
    Windows 10磁盘占用100%解决办法
    关于android:windowNoTitle不起作用的解决办法
    Android TextView 文字居中
    android studio上传项目到github报错Successfully created project 'Demo' on GitHub, but initial commit failed:
    Android开发中string.xml文件的使用
    Android TextView内容过长加省略号,点击显示全部内容
    Retrofit2访问数据的例子,kotlin和anko
    Android提高21篇之一:MediaPlayer
    android4.0蓝牙使能的详细解析
  • 原文地址:https://www.cnblogs.com/wang-jing/p/4737601.html
Copyright © 2020-2023  润新知