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;
  }; 
underscore collections的更多相关文章
- Underscore.js (1.7.0)-集合(Collections)(25)
		稽核函数(数组或对象) each_.each(list, iteratee, [context]) 别名: forEach 遍历list中的所有元素,按顺序用遍历输出每个元素.如果传递了context ... 
- 【初探Underscore】再说模版引擎
		前言 Underscore 是一个JavaScript实用库,提供了类似Prototype.js (或 Ruby)的一些功能,但是没有扩展任何JavaScript内置对象. 它弥补了部分jQuery没 ... 
- Underscore.js 初探
		一. 简介 Underscore 这个单词的意思是“下划线”. Underscore.js 是一个 JavaScript 工具库,提供了一整套的辅助方法供你使用. Think that - ... 
- underscore 笔记
		//reduce是汇总 递归 var perDesc=[ {name: "haha", "email": "haha@email.com"} ... 
- underscore.js 一个强大的js函数库
		Underscore提供的100多个函数,主要涉及对Collection.Object.Array.Function的操作: Collections(集合) each, map, reduce, re ... 
- underscore.js框架使用
		Underscore.js是一个很精干的库,压缩后只有4KB.它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程.MVC框架Backbone.js就将这个库作为自 ... 
- underscoreJS的Collections 的API
		<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ... 
- Python 模块collections
		1.深入理解python中的tuple的功能 基本特性 # 可迭代 name_tuple = ('0bug', '1bug', '2bug') for name in name_tuple: prin ... 
- 常用模块之hashlib,subprocess,logging,re,collections
		hashlib 什么是hashlib 什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,M ... 
随机推荐
- 2018 Multi-University Training Contest 4-Glad You Came(hdu 6356)
			一.思路 线段树维护一个区间最小值,然后对于每次操作,做区间更新即可.要注意的是,在更新的时候,记得剪枝:如果当前更新的值$v \le minv$(minv为当前线段树节点所管辖区间的最小值),直接返 ... 
- Oracle 和 MySQL的区别(不完整)
			1. Oracle对单双引号要求的很死,一般不准用双引号,不然会报错.MySQL 单双引号都可以. 2. 事务提交方式:Oracle 默认手动提交,MySQL 默认自动提交. 3. 分页:MySQL有 ... 
- 全面解析python类的绑定方法与非绑定方法
			类中的方法有两类: 绑定方法 非绑定方法 一.绑定方法 1.对象的绑定方法 首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的.下面,我们通过实例,来慢慢解析绑定方法的应用. ... 
- Protocol入门
			参考:http://haoxiang.org/2011/08/ios-delegate-and-protocol/ 介绍: Protocol在iOS中就是协议,简单的理解就是一组函数的集合,这个集合中 ... 
- html链接路径
			html链接的相对路径与绝对路径 绝对路径 完整的一个路径就是绝对路径,即包含schema://host[:port#]/path/.../[?query-string][#anchor] 例:htt ... 
- 网络通信和TCP详解
			交换机.路由器.服务器组网 1. 通信过程(pc+switch+router+server) 较为复杂的通信过程如:访问 www.baidu.com 注意:一定要配置 PC:IP.NETMASK.DF ... 
- 529. Minesweeper
			▶ 扫雷的扩展判定.已知棋盘上所有点的情况(雷区 'M',已翻开空白区 'B',未翻开空白区 'E',数字区 '1' ~ '8'),现在给定一个点击位置(一定在空白区域),若命中雷区则将被命中的 M ... 
- struts2配置默认首页
			配置struts2 默认欢迎页的几种办法: 1.首先需要明确的是struts过滤器配置映射的模式是路径匹配还是扩展匹配,如果url-pattern配置为/*,如果不做特殊处理,是不会转到welcome ... 
- python's default parameter
			[python's default parameter] 对于值类型(int.double)的default函数参数,函数不会保存对默认类型的修改.对于mutable objectd类型的默认参数,会 ... 
- 编程, 细心永远都不嫌多(记录java连接数据库的一个错误)
			最近在学习Java连接oracle数据库操作, 无意间一个小问题, 浪费了一个下午和半个晚上去找这个错误, 本来可以做更多的事情的, 现将这个错误贴出来, 每次看到, 定将勉励! .......... ... 
