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的更多相关文章

  1. Underscore.js (1.7.0)-集合(Collections)(25)

    稽核函数(数组或对象) each_.each(list, iteratee, [context]) 别名: forEach 遍历list中的所有元素,按顺序用遍历输出每个元素.如果传递了context ...

  2. 【初探Underscore】再说模版引擎

    前言 Underscore 是一个JavaScript实用库,提供了类似Prototype.js (或 Ruby)的一些功能,但是没有扩展任何JavaScript内置对象. 它弥补了部分jQuery没 ...

  3. Underscore.js 初探

    一. 简介   Underscore 这个单词的意思是“下划线”.   Underscore.js 是一个 JavaScript 工具库,提供了一整套的辅助方法供你使用.   Think that - ...

  4. underscore 笔记

    //reduce是汇总 递归 var perDesc=[ {name: "haha", "email": "haha@email.com"} ...

  5. underscore.js 一个强大的js函数库

    Underscore提供的100多个函数,主要涉及对Collection.Object.Array.Function的操作: Collections(集合) each, map, reduce, re ...

  6. underscore.js框架使用

    Underscore.js是一个很精干的库,压缩后只有4KB.它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程.MVC框架Backbone.js就将这个库作为自 ...

  7. underscoreJS的Collections 的API

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Python 模块collections

    1.深入理解python中的tuple的功能 基本特性 # 可迭代 name_tuple = ('0bug', '1bug', '2bug') for name in name_tuple: prin ...

  9. 常用模块之hashlib,subprocess,logging,re,collections

    hashlib 什么是hashlib 什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,M ...

随机推荐

  1. laravel Hash密码 校对

    laravel加密 是使用hash不可逆的,但是可以对加密后的密码进行校对 $data = $r->all();$id = $data['id'];$user_password = bcrypt ...

  2. Accessing data in Hadoop using dplyr and SQL

    If your primary objective is to query your data in Hadoop to browse, manipulate, and extract it into ...

  3. debian修改ssh端口

    vim /etc/ssh/sshd_config,修改port为你想要的端口 invoke-rc.d ssh restart 客户端连接: ssh 142.4.125.90 -l root -p875 ...

  4. Windows 10 修改系统环境变量后,CMD生效,Powershell未生效

    Windows 10 修改系统环境变量后 1.CMD重新打开,新环境变量已经生效: 2.Shift+右键Powershell重新打开,新环境变量没有生效: 3.貌似服务(Apache24)中使用的环境 ...

  5. display:table; 也可以实现 div 始终和内包的图片大小相同

    display:table; 也可以实现 div 始终和内包的图片大小相同

  6. Oracle Database PSU/CPU

    1. 什么是PSU/CPU?CPU: Critical Patch UpdateOracle对于其产品每个季度发行一次的安全补丁包,通常是为了修复产品中的安全隐患. PSU: Patch Set Up ...

  7. oracle9i-11.2安装包及补丁包下载链接

    ORACLE 9i Oracle9i Database Release 2 Enterprise/Standard/Personal Edition for Windows NT/2000/XPhtt ...

  8. OpenCL 事件的使用,以及回调函数

    ▶ 事件的两种使用方法.第一种是用事件 a 标记进入命令队列的操作 A,于是后续进入命令队列的操作 B 可以被要求等到前面事件 a 完成(即操作 A 完成)以后才能开始调度执行.第二种是使用用户自定义 ...

  9. 让别人能登陆你的mysql

    线上的数据库肯定是不能轻易在开发新功能的时候动的,如果你的数据库跟线上不一样了又没有新数据库的备份,就很麻烦. 当然去动线上数据库,出了什么问题我是不想背锅的. 最稳健的办法!让管理线上数据库的同学, ...

  10. Selenium Webdriver——Chrome调试Xpath

    自己通过手写的Xpath要验证是否正确定位到元素,可以通过谷歌浏览器的Console功能(F12) 在console 输入:$x("") 定位去哪儿网的出发输入框: <inp ...