Underscore 是一个JavaScript实用库,提供了类似Prototype.js (或 Ruby)的一些功能,但是没有继承任何JavaScript内置对象。它弥补了部分jQuery没有实现的功能,同时又是Backbone.js必不可少的部分。
Underscore提供了80多个函数,包括常用的: map, select, invoke — 当然还有更多专业的辅助函数,如:函数绑定, JavaScript模板功能, 强类型相等测试, 等等. 在新的浏览器中, 有许多函数如果浏览器本身直接支持,将会采用原生的,如 forEach, map, reduce, filter, every, some 和 indexOf.
一个完整的 测试评分 可以给您更详细的对比.
您也可以阅读 带注释的源码.
此项目 在GitHub托管. 您可以在 issues页面报告Bug或者讨论功能, 或者 Freenode 上的 #documentcloud 频道, 或者发推到 @documentcloud.
Underscore 是一个DocumentCloud的开源组件.
开发版 (1.7.0) | 46kb, 未压缩版, 含大量注释 |
生产版 (1.7.0) | 5.2kb, 最简化并用Gzip压缩 (Source Map) |
不稳定版 | 未发布版本, 当前开发中的 master 分支, 如果实用此版本, 风险自负 |
each_.each(list, iterator, [context])
别名: forEach
对一个 list 的所有元素进行迭代, 对每一个元素执行 iterator
函数. iterator 和 context 对象绑定, 如果传了这个参数. 每次 iterator 的调用将会带有三个参数:
(element, index, list). 如果 list 是一个 JavaScript 对象, iterator 的参数将会是 (value, key, list). 如果有原生的 forEach 函数就会用原生的代替.
_.each([1, 2, 3], alert); => 依次alert每个数字... _.each({one: 1, two: 2, three: 3}, alert); => 依此alert每个数字...
Note: Collection functions work on arrays, objects, and array-like objects such as arguments, NodeList and similar. But it works by duck-typing, so avoid passing objects with a numeric length property. It's also good to note that an each loop cannot be broken out of — to break, use _.find instead.
map_.map(list, iterator, [context])
别名: collect
映射 list 里的每一个值, 通过一个转换函数(iterator)产生一个新的数组. 如果有原生的 map 函数, 将用之代替. 如果 list 是一个 JavaScript 对象,
iterator的参数将会是 (value, key, list).
_.map([1, 2, 3], function(num){ return num * 3; }); => [3, 6, 9] _.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; }); => [3, 6, 9]
reduce_.reduce(list, iterator, memo, [context])
别名: inject, foldl
也被称为 inject 和 foldl, reduce 将一个
list 里的所有值归结到一个单独的数值. Memo 是归结的初始值, 而且每一步都由
iterator返回. 迭代器 iterator 会传入四个参数: memo,
value 和迭代的索引index (或 key),
最后还有对整个 list 的一个引用.
var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); => 6
reduceRight_.reduceRight(list, iterator, memo, [context])
别名: foldr
reduce的右结合版本. 如果可能, 将调用
JavaScript 1.8 版本原生的 reduceRight. Foldr
在 JavaScript 中并没那么有用, 人们对它的评价并不好.
var list = [[0, 1], [2, 3], [4, 5]]; var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); => [4, 5, 2, 3, 0, 1]
find_.find(list, iterator, [context])
别名: detect
在 list 里的每一项进行查找, 返回第一个符合
测试(iterator)条件的元素. 此函数只返回第一个符合条件的元素, 并不会遍历整个list.
var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => 2
filter_.filter(list, iterator, [context])
别名: select
在 list 里的每一项进行查找, 返回一个符合测试 (iterator) 条件的所有元素的集合. 如果存在原生的 filter 方法, 将采用原生的.
var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => [2, 4, 6]
where_.where(list, properties)
遍历 list 里的每一个值, 返回包含 properties 里所有
key-value 组合的对象的数组.
_.where(listOfPlays, {author: "Shakespeare", year: 1611}); => [{title: "Cymbeline", author: "Shakespeare", year: 1611}, {title: "The Tempest", author: "Shakespeare", year: 1611}]
findWhere_.findWhere(list, properties)
Looks through the list and returns the first value that matches
all of the key-value pairs listed in properties.
If no match is found, or if list is empty, undefined will be returned.
_.findWhere(publicServicePulitzers, {newsroom: "The New York Times"}); => {year: 1918, newsroom: "The New York Times", reason: "For its public service in publishing in full so many official reports, documents and speeches by European statesmen relating to the progress and conduct of the war."}
reject_.reject(list, iterator, [context])
返回在 list 不能通过测试 (iterator) 的所有元素的集合. 与 filter 相反.
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => [1, 3, 5]
every_.every(list, [iterator], [context])
别名: all
如果所有在 list 里的元素通过了 iterator 的测试, 返回 true.
如果存在则使用原生的 every 方法.
_.every([true, 1, null, 'yes'], _.identity); => false
some_.some(list, [iterator], [context])
别名: any
如果任何 list 里的任何一个元素通过了 iterator 的测试, 将返回 true.
一旦找到了符合条件的元素, 就直接中断对list的遍历. 如果存在, 将会使用原生的 some 方法.
_.some([null, 0, 'yes', false]); => true
contains_.contains(list, value)
别名: include
如果 value 存在与 list 里, 返回 true.
如果 list 是一个数组, 内部会使用 indexOf.
_.contains([1, 2, 3], 3); => true
invoke_.invoke(list, methodName, [*arguments])
在 list 里的每个元素上调用名为 methodName 的函数.
任何附加的函数传入, invoke 将会转给要调用的函数.
_.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); => [[1, 5, 7], [1, 2, 3]]
pluck_.pluck(list, propertyName)
一个 map 通常用法的简便版本: 提取一个集合里指定的属性值.
var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}]; _.pluck(stooges, 'name'); => ["moe", "larry", "curly"]
max_.max(list, [iterator], [context])
返回 list 里最大的元素. 如果传入了 iterator,
它将用来比较每个值.
var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}]; _.max(stooges, function(stooge){ return stooge.age; }); => {name: 'curly', age: 60};
min_.min(list, [iterator], [context])
返回 list 里最小的元素. 如果传入了 iterator,
它将用来比较每个值.
var numbers = [10, 5, 100, 2, 1000]; _.min(numbers); => 2
sortBy_.sortBy(list, iterator, [context])
返回一个经过排序的 list 副本, 用升序排列 iterator 返回的值.
迭代器也可以用字符串的属性来进行比较(如length).
_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); }); => [5, 4, 6, 3, 1, 2]
groupBy_.groupBy(list, iterator)
把一个集合分为多个集合, 通过 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"]}
indexBy_.indexBy(list, iteratee, [context])
Given a list, and an iteratee function that returns a
key for each element in the list (or a property name),
returns an object with an index of each item.
Just like groupBy, but for when you know your
keys are unique.
var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}]; _.indexBy(stooges, 'age'); => { "40": {name: 'moe', age: 40}, "50": {name: 'larry', age: 50}, "60": {name: 'curly', age: 60} }
countBy_.countBy(list, iterator)
把一个数组分组并返回每一组内对象个数.
与 groupBy 相似, 但不是返回一组值,
而是组内对象的个数.
_.countBy([1, 2, 3, 4, 5], function(num) { return num % 2 == 0 ? 'even': 'odd'; }); => {odd: 3, even: 2}
shuffle_.shuffle(list)
返回一个随机乱序的 list 副本, 使用
Fisher-Yates shuffle 来进行随机乱序.
_.shuffle([1, 2, 3, 4, 5, 6]); => [4, 1, 6, 3, 5, 2]
sample_.sample(list, [n])
从 list 里进行随机取样. 传一个数字 n 来决定返回的样本个数,
否则只返回一个样本.
_.sample([1, 2, 3, 4, 5, 6]); => 4 _.sample([1, 2, 3, 4, 5, 6], 3); => [1, 6, 2]
toArray_.toArray(list)
将一个 list (任何可以被进行迭代的对象)转换成一个数组. 在转换 arguments 对象时非常有用.
(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4); => [2, 3, 4]
size_.size(list)
返回 list 里所有元素的个数.
_.size({one: 1, two: 2, three: 3}); => 3
partition_.partition(array, predicate)
Split array into two arrays: one whose elements all satisfy
predicate and one whose elements all do not satisfy predicate.
_.partition([0, 1, 2, 3, 4, 5], isOdd); => [[1, 3, 5], [0, 2, 4]]
注意: 所有数组函数都可以用在 arguments 对象上. 然而, Underscore 函数的设计并不只是针对稀疏数组的.
first_.first(array, [n])
别名: head, take
返回数组 array 里的第一个元素. 如果传了参数 n
将返回数组里前 n 个元素.
_.first([5, 4, 3, 2, 1]); => 5
initial_.initial(array, [n])
返回一个数组里除了最后一个元素以外的所有元素. 在arguments对象上特别有用.
传参 n 将排除数组最后的 n 个元素.
_.initial([5, 4, 3, 2, 1]); => [5, 4, 3, 2]
last_.last(array, [n])
返回数组 array 里的最后一个元素. 传参 n 将返回
数组里的后 n 个元素.
_.last([5, 4, 3, 2, 1]); => 1
rest_.rest(array, [index])
别名: tail, drop
返回一个数组里除了第一个以外 剩余的 所有元素. 传参 index
将返回除了第 index 个元素以外剩余的所有元素.
_.rest([5, 4, 3, 2, 1]); => [4, 3, 2, 1]
compact_.compact(array)
返回一个数组 array 除空(真值检验为false)后的副本.
在JavaScript里, false, null, 0, "",
undefined 和 NaN 真值检验的结果都为false.
_.compact([0, 1, false, 2, '', 3]); => [1, 2, 3]
flatten_.flatten(array, [shallow])
将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组.
如果传参 shallow 为true, 数组只转换第一层.
_.flatten([1, [2], [3, [[4]]]]); => [1, 2, 3, 4]; _.flatten([1, [2], [3, [[4]]]], true); => [1, 2, 3, [[4]]];
without_.without(array, [*values])
返回一个除去所有 values 后的 array 副本.
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); => [2, 3, 4]
union_.union(*arrays)
返回传入的多个数组 arrays 结合后的数组: 且所有数组元素都是唯一的,
传入的数组可以是一个或多个数组 arrays.
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); => [1, 2, 3, 101, 10]
intersection_.intersection(*arrays)
返回一个多个数组 arrays 的交集.
即返回的数组里每个元素, 都存在于参数 arrays 每个数组里.
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); => [1, 2]
difference_.difference(array, *others)
跟 without 相似, 但是返回的数组是 array 里跟别的数组 other 里不一样的元素.
_.difference([1, 2, 3, 4, 5], [5, 2, 10]); => [1, 3, 4]
uniq_.uniq(array, [isSorted], [iterator])
别名: unique
返回 array 去重后的副本, 使用 === 做相等测试.
如果您确定 array 已经排序,
给 isSorted 参数传如 true, 此函数将使用更快的算法.
如果要处理对象元素, 传参 iterator 来获取要对比的属性.
_.uniq([1, 2, 1, 3, 1, 4]); => [1, 2, 3, 4]
zip_.zip(*arrays)
合并 arrays 里每一个数组的每个元素, 并保留对应位置.
在合并分开保存的数据时很有用. 如果你用来处理矩阵嵌套数组时,
zip.apply 可以做类似的效果.
_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]); => [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]] _.zip.apply(_, arrayOfRowsOfData); => arrayOfColumnsOfData
object_.object(list, [values])
把数组转换成对象. 传一个或多个
[key, value] 形式的数组,
或者一个包含key的数组和一个包含value的数组.
_.object(['moe', 'larry', 'curly'], [30, 40, 50]); => {moe: 30, larry: 40, curly: 50} _.object([['moe', 30], ['larry', 40], ['curly', 50]]); => {moe: 30, larry: 40, curly: 50}
indexOf_.indexOf(array, value, [isSorted])
返回元素 value 在数组 array 里的索引位置,
如果元素没在数组 array 中, 将返回 -1. 此函数将使用原生的 indexOf 方法, 除非原生的方法无故消失或者被覆盖重写了, 才使用非原生的.
如果您要处理一个大型数组, 而且确定数组已经排序, 参数 isSorted 可以传 true, 函数将使用更快的二进制搜索来进行处理... 或者, 传一个数字作为
第三个参数, 以便于在指定索引之后开始寻找对应值.
_.indexOf([1, 2, 3], 2); => 1
lastIndexOf_.lastIndexOf(array, value, [fromIndex])
返回元素 value 在数组 arrry 里最后一次出现的索引位置,
如果元素没在数组 array 中, 将返回 -1.
如有可能, 此函数将使用原生的 lastIndexOf 方法. 传参 fromIndex 以便从指定索引开始寻找.
_.lastIndexOf([1, 2, 3, 1, 2, 3], 2); => 4
sortedIndex_.sortedIndex(list, value, [iterator])
为了保持 list 已经排好的顺序, 使用二进制搜索来检测 value
应该 插入到 list 里的所在位置的索引.
如果传入了一个 iterator , 它将用来计算每个值的排名, 包括所传的 value 参数.
_.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
range_.range([start], stop, [step])
一个灵活创建范围内整数数组的函数,
each 和 map 循环整合的简便版本. 如果省略start 参数, 默认为 0; step 默认为 1. 返回一个数组, 包含从 start 到 stop (不包含stop) 范围内, 以 step 递增(减)的整数.
_.range(10); => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] _.range(1, 11); => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] _.range(0, 30, 5); => [0, 5, 10, 15, 20, 25] _.range(0, -10, -1); => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] _.range(0); => []
bind_.bind(function, object, [*arguments])
绑定函数 function 到对象 object 上,
也就是无论何时函数被调用, 函数里的 this 都指向 object.
可选参数 arguments 可以绑定到函数 function , 可以填充函数所需要的参数,
这也被成为 部分应用.
var func = function(greeting){ return greeting + ': ' + this.name }; func = _.bind(func, {name: 'moe'}, 'hi'); func(); => 'hi: moe'
bindAll_.bindAll(object, [*methodNames])
绑定 methodNames 指定的方法到 object 上, 当这些方法被执行时将在对象的上下文执行. 绑定函数用作事件处理时非常方便, 否则函数调用时
this 关键字根本没什么用. 如果不传 methodNames 参数, 对象里的所有方法都被绑定.
var buttonView = { label : 'underscore', onClick: function(){ alert('clicked: ' + this.label); }, onHover: function(){ console.log('hovering: ' + this.label); } }; _.bindAll(buttonView, 'onClick', 'onHover'); // 当按钮被点击, this.label将会取到正确的值, 即buttonView里的label而不是按钮的label. jQuery('#underscore_button').bind('click', buttonView.onClick);
partial_.partial(function, [*arguments])
Partially apply a function by filling in any number of its arguments,
without changing its dynamic this value. A close cousin
of bind.
var add = function(a, b) { return a + b; }; add5 = _.partial(add, 5); add5(10); => 15
memoize_.memoize(function, [hashFunction])
通过缓存计算结果使函数 function 具有记忆功能.
在优化耗时较长的算时法非常有用. 如果传了可选参数
hashFunction, 将用其返回的值作为key来保存函数的运行结果,
以原始函数的参数为基础.
hashFunction 默认使用被缓存函数的第一个参数作为key.
var fibonacci = _.memoize(function(n) { return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2); });
delay_.delay(function, wait, [*arguments])
和 setTimeout 方法很像, 在 wait 毫秒之后调用 function 函数. 如果传了可选参数 arguments, 在函数 function 调用的时候会作为参数传入.
var log = _.bind(console.log, console); _.delay(log, 1000, 'logged later'); => 'logged later' // 一秒钟后显示.defer
_.defer(function, [*arguments])
延迟调用 function 函数, 直到当前调用栈被清空为止, 跟使用 setTimeout 赋予0毫秒的延时很像. 对执行高消耗算法或大型HTML呈现而不阻碍UI更新线程很有用. 如果传了可选参数 arguments, 在函数 function 调用的时候会作为参数传入._.defer(function(){ alert('deferred'); }); // 将在alert显示之前返回这个functionthrottle
_.throttle(function, wait)
返回一个类似于节流阀一样的函数, 当高频率的调用函数, 实际上会每隔 wait 毫秒才会调用一次. 对于高到您感觉不到的高频率执行的函数时非常有用.By default, throttle will execute the function as soon as you call it for the first time, and, if you call it again any number of times during the wait period, as soon as that period is over. If you'd like to disable the leading-edge call, pass {leading: false}, and if you'd like to disable the execution on the trailing-edge, pass
{trailing: false}.var throttled = _.throttle(updatePosition, 100); $(window).scroll(throttled);debounce
_.debounce(function, wait, [immediate])
返回 function 函数的防反跳版本, 将延迟函数的执行(真正的执行)在函数最后一次调用时刻的 wait 毫秒之后. 对于必须在一些输入(多是一些用户操作)停止到达之后执行的行为有帮助。 例如: 渲染一个Markdown格式的评论预览, 当窗口停止改变大小之后重新计算布局, 等等.传参 immediate 为 true 会让 debounce 在 wait 间隔之后 触发最后的函数调用而不是最先的函数调用. 在类似不小心点了提交按钮两下而提交了两次的情况下很有用.
var lazyLayout = _.debounce(calculateLayout, 300); $(window).resize(lazyLayout);once
_.once(function)
创建一个只能运行一次的函数. 重复调用此修改过的函数会没有效果, 只会返回第一次执行时返回的结果. 作为初始化函数使用时非常有用, 不用再设一个boolean值来检查是否已经初始化完成.var initialize = _.once(createApplication); initialize(); initialize(); // Application只会创建一次.after
_.after(count, function)
创建一个函数, 只有在运行了 count 次之后才有效果. 在处理同组异步请求返回结果时, 如果你要确保同组里所有异步请求完成之后才 执行这个函数, 这将非常有用.var renderNotes = _.after(notes.length, render); _.each(notes, function(note) { note.asyncSave({success: renderNotes}); }); // renderNotes 只会运行一次, 而且是在所有 notes 保存完毕之后才执行.before
_.before(count, function)
Creates a version of the function that can be called no more than count times. The result of the last function call is memoized and returned when count has been reached.var monthlyMeeting = _.before(3, askForRaise); monthlyMeeting(); monthlyMeeting(); monthlyMeeting(); // the result of any subsequent calls is the same as the second callwrap
_.wrap(function, wrapper)
将第一个函数 function 封装到函数 wrapper 里面, 并把函数 function 作为第一个参数传给 wrapper. 这样可以让 wrapper 在 function 运行之前和之后 执行代码, 调整参数然后附有条件地执行.var hello = function(name) { return "hello: " + name; }; hello = _.wrap(hello, function(func) { return "before, " + func("moe") + ", after"; }); hello(); => 'before, hello: moe, after'negate
_.negate(predicate)
Returns a new negated version of the predicate function.var isFalsy = _.negate(Boolean); _.find([-2, -1, 0, 1, 2], isFalsy); => 0compose
_.compose(*functions)
返回函数集 functions 组合后的复合函数, 也就是一个函数执行完之后把返回的结果再作为参数赋给下一个函数来执行. 以此类推. 在数学里, 把函数 f(), g(), 和 h() 组合起来可以得到复合函数 f(g(h())).var greet = function(name){ return "hi: " + name; }; var exclaim = function(statement){ return statement.toUpperCase() + "!"; }; var welcome = _.compose(greet, exclaim); welcome('moe'); => 'hi: MOE!'对象函数
keys
_.keys(object)
获取 object 对象的所有属性名._.keys({one: 1, two: 2, three: 3}); => ["one", "two", "three"]values
_.values(object)
获取 object 对象的所有属性值._.values({one: 1, two: 2, three: 3}); => [1, 2, 3]pairs
_.pairs(object)
把一个对象转换成一个 [key, value] 形式的数组._.pairs({one: 1, two: 2, three: 3}); => [["one", 1], ["two", 2], ["three", 3]]invert
_.invert(object)
返回一个 object 的副本, 并且里面键和值是对调的. 要使之有效, 必须确保object里所有的值都是唯一的且可以序列号成字符串._.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"}); => {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};functions
_.functions(object)
别名: methods
返回一个对象里所有的方法名, 而且是已经排序的 — 也就是说, 对象里每个方法(属性值是一个函数)的名称._.functions(_); => ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...extend
_.extend(destination, *sources)
复制 source 对象的所有属性到 destination 对象上, 然后返回 destination 对象. 复制是按顺序的, 所以后面的对象属性会把前面的对象属性覆盖掉(如果有重复)._.extend({name: 'moe'}, {age: 50}); => {name: 'moe', age: 50}pick
_.pick(object, *keys)
返回一个 object 对象的副本, 过滤掉除了 keys 以外的所有属性(一个或多个)._.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age'); => {name: 'moe', age: 50} _.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) { return _.isNumber(value); }); => {age: 50}omit
_.omit(object, *keys)
返回一个 object 对象的副本, 过滤掉了黑名单里的 keys (keys可以是单个key也可以是包含多个key的数组)._.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid'); => {name: 'moe', age: 50} _.omit({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) { return _.isNumber(value); }); => {name: 'moe', userid: 'moe1'}defaults
_.defaults(object, *defaults)
用 defaults 对象里的默认值来填充 object 对象里遗漏的属性值, 并返回 object 对象. 当属性值已被填充遗漏, 再添加属性值就没用了.var iceCream = {flavor: "chocolate"}; _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"}); => {flavor: "chocolate", sprinkles: "lots"}clone
_.clone(object)
克隆对象 object. 任何嵌套的对象或数组将会被引用, 而不是复制._.clone({name: 'moe'}); => {name: 'moe'};tap
_.tap(object, interceptor)
用对象 object 作为参数来调用函数 interceptor, 然后返回 object 对象. 此方法的主要意图是作为函数链式调用 的一环, 为了对此对象执行操作并返回对象本身._.chain([1,2,3,200]) .filter(function(num) { return num % 2 == 0; }) .tap(alert) .map(function(num) { return num * num }) .value(); => // [2, 200] (alerted) => [4, 40000]has
_.has(object, key)
判断对象 object 包含指定的属性 key 吗? 和 object.hasOwnProperty(key) 相同, 但是使用了 hasOwnProperty 函数的安全引用, 更多请参考 意外重写._.has({a: 1, b: 2, c: 3}, "b"); => trueproperty
_.property(key)
Returns a function that will itself return the key property of any passed-in object.var moe = {name: 'moe'}; 'moe' === _.property('name')(moe); => truematches
_.matches(attrs)
Returns a predicate function that will tell you if a passed in object contains all of the key/value properties present in attrs.var ready = _.matches({selected: true, visible: true}); var readyToGoList = _.filter(list, ready);isEqual
_.isEqual(object, other)
执行优化过的算法来对两个对象进行深度的相等测试, 来判定两个对象是否相等(非全等).var moe = {name: 'moe', luckyNumbers: [13, 27, 34]}; var clone = {name: 'moe', luckyNumbers: [13, 27, 34]}; moe == clone; => false _.isEqual(moe, clone); => trueisEmpty
_.isEmpty(object)
如果 object 里没包含任何东西, 将返回 true._.isEmpty([1, 2, 3]); => false _.isEmpty({}); => trueisElement
_.isElement(object)
如果 object 是一个DOM元素, 将返回 true._.isElement(jQuery('body')[0]); => trueisArray
_.isArray(object)
如果 object 是一个数组, 将返回 true.(function(){ return _.isArray(arguments); })(); => false _.isArray([1,2,3]); => trueisObject
_.isObject(value)
如果 value 是一个对象, 将返回 true. 注意在JavaScript中数组和函数都是对象, 而普通的字符串和数字不是._.isObject({}); => true _.isObject(1); => falseisArguments
_.isArguments(object)
如果 object 是参数(Arguments)对象, 将返回 true.(function(){ return _.isArguments(arguments); })(1, 2, 3); => true _.isArguments([1,2,3]); => falseisFunction
_.isFunction(object)
如果 object 是函数, 将返回 true._.isFunction(alert); => trueisString
_.isString(object)
如果 object 是字符串, 将返回 true._.isString("moe"); => trueisNumber
_.isNumber(object)
如果 object 是一个数字(包括NaN), 将返回 true._.isNumber(8.4 * 5); => trueisFinite
_.isFinite(object)
如果 object 是一个有限的数字, 将返回 true._.isFinite(-101); => true _.isFinite(-Infinity); => falseisBoolean
_.isBoolean(object)
如果 object 是布尔值(true 或 false), 将返回 true._.isBoolean(null); => falseisDate
_.isDate(object)
如果 object 是时间对象, 将返回 true._.isDate(new Date()); => trueisRegExp
_.isRegExp(object)
如果 object 是正则表达式对象, 将返回 true_.isRegExp(/moe/); => trueisNaN
_.isNaN(object)
如果 object 是 NaN, 将返回 true.
注意: 这与原生的 isNaN 函数不一样, 原生的传参即使是 undefined 也会返回true._.isNaN(NaN); => true isNaN(undefined); => true _.isNaN(undefined); => falseisNull
_.isNull(object)
如果 object 的值是 null, 将返回 true._.isNull(null); => true _.isNull(undefined); => falseisUndefined
_.isUndefined(value)
如果 variable 是 undefined, 将会返回 true ._.isUndefined(window.missingVariable); => true实用功能
noConflict
_.noConflict()
把 "_" 变量的控制权还给它原有的所有者. 返回一个 Underscore 对象的引用.var underscore = _.noConflict();identity
_.identity(value)
返回与传入参数相等的值. 相当于数学里的: f(x) = x
这个函数看似无用, 但是在Underscore里被用作默认的迭代器iterator.var moe = {name: 'moe'}; moe === _.identity(moe); => trueconstant
_.constant(value)
Creates a function that returns the same value that is used as the argument of _.constant.var moe = {name: 'moe'}; moe === _.constant(moe)(); => truenoop
_.noop()
Returns undefined irrespective of the arguments passed to it. Useful as the default for optional callback arguments.obj.initialize = _.noop;times
_.times(n, iterator, [context])
调用指定的 iterator 函数 n 次. iterator 的每一次调用都带 index 参数._(3).times(function(n){ genie.grantWishNumber(n); });random
_.random(min, max)
Returns a random integer between min and max, inclusive. If you only pass one argument, it will return a number between 0 and that number._.random(0, 100); => 42mixin
_.mixin(object)
Allows you to extend Underscore with your own utility functions. Pass a hash of {name: function} definitions to have your functions added to the Underscore object, as well as the OOP wrapper._.mixin({ capitalize: function(string) { return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase(); } }); _("fabio").capitalize(); => "Fabio"iteratee
_.iteratee(value, [context], [argCount])
A mostly-internal function to generate callbacks that can be applied to each element in a collection, returning the desired result — either identity, an arbitrary callback, a property matcher, or a property accessor.
The full list of Underscore methods that transform predicates through _.iteratee is map, find, filter, reject, every, some, max, min, sortBy, groupBy, indexBy, countBy, sortedIndex, partition, and unique.var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}]; _.map(stooges, _.iteratee('age')); => [25, 21, 23];uniqueId
_.uniqueId([prefix])
Generate a globally-unique id for client-side models or DOM elements that need one. If prefix is passed, the id will be appended to it._.uniqueId('contact_'); => 'contact_104'escape
_.escape(string)
Escapes a string for insertion into HTML, replacing &, <, >, ", `, and ' characters._.escape('Curly, Larry & Moe'); => "Curly, Larry & Moe"unescape
_.unescape(string)
The opposite of escape, replaces &, <, >, ", ` and ' with their unescaped counterparts._.unescape('Curly, Larry & Moe'); => "Curly, Larry & Moe"result
_.result(object, property)
If the value of the named property is a function then invoke it with the object as context; otherwise, return it.var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }}; _.result(object, 'cheese'); => "crumpets" _.result(object, 'stuff'); => "nonsense"now
_.now()
Returns an integer timestamp for the current time, using the fastest method available in the runtime. Useful for implementing timing/animation functions._.now(); => 1392066795351template
_.template(templateString, [settings])
Compiles JavaScript templates into functions that can be evaluated for rendering. Useful for rendering complicated bits of HTML from JSON data sources. Template functions can both interpolate variables, using <%= … %>, as well as execute arbitrary JavaScript code, with <% … %>. If you wish to interpolate a value, and have it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a data object that has properties corresponding to the template's free variables. The settings argument should be a hash containing any _.templateSettings that should be overridden.var compiled = _.template("hello: <%= name %>"); compiled({name: 'moe'}); => "hello: moe" var template = _.template("<b><%- value %></b>"); template({value: '<script>'}); => "<b><script></b>"You can also use print from within JavaScript code. This is sometimes more convenient than using <%= ... %>.
var compiled = _.template("<% print('Hello ' + epithet); %>"); compiled({epithet: "stooge"}); => "Hello stooge"If ERB-style delimiters aren't your cup of tea, you can change Underscore's template settings to use different symbols to set off interpolated code. Define an interpolate regex to match expressions that should be interpolated verbatim, an escape regex to match expressions that should be inserted after being HTML escaped, and an evaluate regex to match expressions that should be evaluated without insertion into the resulting string. You may define or omit any combination of the three. For example, to perform Mustache.js style templating:
_.templateSettings = { interpolate: /\{\{(.+?)\}\}/g }; var template = _.template("Hello {{ name }}!"); template({name: "Mustache"}); => "Hello Mustache!"By default, template places the values from your data in the local scope via the with statement. However, you can specify a single variable name with the variable setting. This can significantly improve the speed at which a template is able to render.
_.template("Using 'with': <%= data.answer %>", {variable: 'data'})({answer: 'no'}); => "Using 'with': no"Precompiling your templates can be a big help when debugging errors you can't reproduce. This is because precompiled templates can provide line numbers and a stack trace, something that is not possible when compiling templates on the client. The source property is available on the compiled template function for easy precompilation.
<script> JST.project = <%= _.template(jstText).source %>; </script>Chaining
You can use Underscore in either an object-oriented or a functional style, depending on your preference. The following two lines of code are identical ways to double a list of numbers.
_.map([1, 2, 3], function(n){ return n * 2; }); _([1, 2, 3]).map(function(n){ return n * 2; });Calling chain will cause all future method calls to return wrapped objects. When you've finished the computation, call value to retrieve the final value. Here's an example of chaining together a map/flatten/reduce, in order to get the word count of every word in a song.
var lyrics = [ {line: 1, words: "I'm a lumberjack and I'm okay"}, {line: 2, words: "I sleep all night and I work all day"}, {line: 3, words: "He's a lumberjack and he's okay"}, {line: 4, words: "He sleeps all night and he works all day"} ]; _.chain(lyrics) .map(function(line) { return line.words.split(' '); }) .flatten() .reduce(function(counts, word) { counts[word] = (counts[word] || 0) + 1; return counts; }, {}) .value(); => {lumberjack: 2, all: 4, night: 2 ... }In addition, the Array prototype's methods are proxied through the chained Underscore object, so you can slip a reverse or a push into your chain, and continue to modify the array.
chain
_.chain(obj)
Returns a wrapped object. Calling methods on this object will continue to return wrapped objects until value is called.var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}]; var youngest = _.chain(stooges) .sortBy(function(stooge){ return stooge.age; }) .map(function(stooge){ return stooge.name + ' is ' + stooge.age; }) .first() .value(); => "moe is 21"value
_(obj).value()
Extracts the value of a wrapped object._([1, 2, 3]).value(); => [1, 2, 3]Links & Suggested Reading
The Underscore documentation is also available in Simplified Chinese.
Underscore.lua, a Lua port of the functions that are applicable in both languages. Includes OOP-wrapping and chaining. (source)
Underscore.m, an Objective-C port of many of the Underscore.js functions, using a syntax that encourages chaining. (source)
_.m, an alternative Objective-C port that tries to stick a little closer to the original Underscore.js API. (source)
Underscore.php, a PHP port of the functions that are applicable in both languages. Includes OOP-wrapping and chaining. (source)
Underscore-perl, a Perl port of many of the Underscore.js functions, aimed at on Perl hashes and arrays. (source)
Underscore.cfc, a Coldfusion port of many of the Underscore.js functions. (source)
Underscore.string, an Underscore extension that adds functions for string-manipulation: trim, startsWith, contains, capitalize, reverse, sprintf, and more.
Ruby's Enumerable module.
Prototype.js, which provides JavaScript with collection functions in the manner closest to Ruby's Enumerable.
Oliver Steele's Functional JavaScript, which includes comprehensive higher-order function support as well as string lambdas.
Michael Aufreiter's Data.js, a data manipulation + persistence library for JavaScript.
Python's itertools.
PyToolz, a Python port that extends itertools and functools to include much of the Underscore API.
Funcy, a practical collection of functional helpers for Python, partially inspired by Underscore.
Change Log
1.6.0 — February 10, 2014 — Diff — Docs
1.5.2 — September 7, 2013 — Diff — Docs
1.5.1 — July 8, 2013 — Diff — Docs
1.5.0 — July 6, 2013 — Diff — Docs
1.4.4 — January 30, 2013 — Diff — Docs
1.4.3 — December 4, 2012 — Diff — Docs
1.4.2 — October 6, 2012 — Diff — Docs
1.4.1 — October 1, 2012 — Diff — Docs
1.4.0 — September 27, 2012 — Diff — Docs
1.3.3 — April 10, 2012 — Diff — Docs
1.3.1 — January 23, 2012 — Diff — Docs
1.3.0 — January 11, 2012 — Diff — Docs
1.2.4 — January 4, 2012 — Diff — Docs
1.2.3 — December 7, 2011 — Diff — Docs
1.2.2 — November 14, 2011 — Diff — Docs
1.2.1 — October 24, 2011 — Diff — Docs
1.2.0 — October 5, 2011 — Diff — Docs
1.1.7 — July 13, 2011 — Diff — Docs
Added _.groupBy, which aggregates a collection into groups of like items.
Added _.union and _.difference, to complement the
(re-named) _.intersection.
Various improvements for support of sparse arrays.
_.toArray now returns a clone, if directly passed an array.
_.functions now also returns the names of functions that are present
in the prototype chain.
1.1.6 — April 18, 2011 — Diff — Docs
Added _.after, which will return a function that only runs after
first being called a specified number of times.
_.invoke can now take a direct function reference.
_.every now requires an iterator function to be passed, which
mirrors the ECMA5 API.
_.extend no longer copies keys when the value is undefined.
_.bind now errors when trying to bind an undefined value.
1.1.5 — March 20, 2011 — Diff — Docs
Added an _.defaults function, for use merging together JS objects
representing default options.
Added an _.once function, for manufacturing functions that should
only ever execute a single time.
_.bind now delegates to the native ECMAScript 5 version,
where available.
_.keys now throws an error when used on non-Object values, as in
ECMAScript 5.
Fixed a bug with _.keys when used over sparse arrays.
1.1.4 — January 9, 2011 — Diff — Docs
Improved compliance with ES5's Array methods when passing null
as a value. _.wrap now correctly sets this for the
wrapped function. _.indexOf now takes an optional flag for
finding the insertion index in an array that is guaranteed to already
be sorted. Avoiding the use of .callee, to allow _.isArray
to work properly in ES5's strict mode.
1.1.3 — December 1, 2010 — Diff — Docs
In CommonJS, Underscore may now be required with just:
var _ = require("underscore").
Added _.throttle and _.debounce functions.
Removed _.breakLoop, in favor of an ECMA5-style un-break-able
each implementation — this removes the try/catch, and you'll now have
better stack traces for exceptions that are thrown within an Underscore iterator.
Improved the isType family of functions for better interoperability
with Internet Explorer host objects.
_.template now correctly escapes backslashes in templates.
Improved _.reduce compatibility with the ECMA5 version:
if you don't pass an initial value, the first item in the collection is used.
_.each no longer returns the iterated collection, for improved
consistency with ES5's forEach.
1.1.2 — October 15, 2010 — Diff — Docs
Fixed _.contains, which was mistakenly pointing at
_.intersect instead of _.include, like it should
have been. Added _.unique as an alias for _.uniq.
1.1.1 — October 5, 2010 — Diff — Docs
Improved the speed of _.template, and its handling of multiline
interpolations. Ryan Tenney contributed optimizations to many Underscore
functions. An annotated version of the source code is now available.
1.1.0 — August 18, 2010 — Diff — Docs
The method signature of _.reduce has been changed to match
the ECMAScript 5 signature, instead of the Ruby/Prototype.js version.
This is a backwards-incompatible change. _.template may now be
called with no arguments, and preserves whitespace. _.contains
is a new alias for _.include.
1.0.4 — June 22, 2010 — Diff — Docs
Andri Möll contributed the _.memoize
function, which can be used to speed up expensive repeated computations
by caching the results.
1.0.3 — June 14, 2010 — Diff — Docs
Patch that makes _.isEqual return false if any property
of the compared object has a NaN value. Technically the correct
thing to do, but of questionable semantics. Watch out for NaN comparisons.
1.0.2 — March 23, 2010 — Diff — Docs
Fixes _.isArguments in recent versions of Opera, which have
arguments objects as real Arrays.
1.0.1 — March 19, 2010 — Diff — Docs
Bugfix for _.isEqual, when comparing two objects with the same
number of undefined keys, but with different names.
1.0.0 — March 18, 2010 — Diff — Docs
Things have been stable for many months now, so Underscore is now
considered to be out of beta, at 1.0. Improvements since 0.6
include _.isBoolean, and the ability to have _.extend
take multiple source objects.
0.6.0 — February 24, 2010 — Diff — Docs
Major release. Incorporates a number of
Mile Frawley's refactors for
safer duck-typing on collection functions, and cleaner internals. A new
_.mixin method that allows you to extend Underscore with utility
functions of your own. Added _.times, which works the same as in
Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray,
and Object.keys.
0.5.8 — January 28, 2010 — Diff — Docs
Fixed Underscore's collection functions to work on
NodeLists and
HTMLCollections
once more, thanks to
Justin Tulloss.
0.5.7 — January 20, 2010 — Diff — Docs
A safer implementation of _.isArguments, and a
faster _.isNumber,
thanks to
Jed Schmidt.
0.5.6 — January 18, 2010 — Diff — Docs
Customizable delimiters for _.template, contributed by
Noah Sloan.
0.5.5 — January 9, 2010 — Diff — Docs
Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.
0.5.4 — January 5, 2010 — Diff — Docs
Fix for multiple single quotes within a template string for
_.template. See:
Rick Strahl's blog post.
0.5.2 — January 1, 2010 — Diff — Docs
New implementations of isArray, isDate, isFunction,
isNumber, isRegExp, and isString, thanks to
a suggestion from
Robert Kieffer.
Instead of doing Object#toString
comparisons, they now check for expected properties, which is less safe,
but more than an order of magnitude faster. Most other Underscore
functions saw minor speed improvements as a result.
Evgeniy Dolzhenko
contributed _.tap,
similar to Ruby 1.9's,
which is handy for injecting side effects (like logging) into chained calls.
0.5.1 — December 9, 2009 — Diff — Docs
Added an _.isArguments function. Lots of little safety checks
and optimizations contributed by
Noah Sloan and
Andri Möll.
0.5.0 — December 7, 2009 — Diff — Docs
[API Changes] _.bindAll now takes the context object as
its first parameter. If no method names are passed, all of the context
object's methods are bound to it, enabling chaining and easier binding.
_.functions now takes a single argument and returns the names
of its Function properties. Calling _.functions(_) will get you
the previous behavior.
Added _.isRegExp so that isEqual can now test for RegExp equality.
All of the "is" functions have been shrunk down into a single definition.
Karl Guertin contributed patches.
0.4.7 — December 6, 2009 — Diff — Docs
Added isDate, isNaN, and isNull, for completeness.
Optimizations for isEqual when checking equality between Arrays
or Dates. _.keys is now 25%–2X faster (depending on your
browser) which speeds up the functions that rely on it, such as _.each.
0.4.6 — November 30, 2009 — Diff — Docs
Added the range function, a port of the
Python
function of the same name, for generating flexibly-numbered lists
of integers. Original patch contributed by
Kirill Ishanov.
0.4.5 — November 19, 2009 — Diff — Docs
Added rest for Arrays and arguments objects, and aliased
first as head, and rest as tail,
thanks to Luke Sutton's patches.
Added tests ensuring that all Underscore Array functions also work on
arguments objects.
0.4.4 — November 18, 2009 — Diff — Docs
Added isString, and isNumber, for consistency. Fixed
_.isEqual(NaN, NaN) to return true (which is debatable).
0.4.3 — November 9, 2009 — Diff — Docs
Started using the native StopIteration object in browsers that support it.
Fixed Underscore setup for CommonJS environments.
0.4.2 — November 9, 2009 — Diff — Docs
Renamed the unwrapping function to value, for clarity.
0.4.1 — November 8, 2009 — Diff — Docs
Chained Underscore objects now support the Array prototype methods, so
that you can perform the full range of operations on a wrapped array
without having to break your chain. Added a breakLoop method
to break in the middle of any Underscore iteration. Added an
isEmpty function that works on arrays and objects.
0.4.0 — November 7, 2009 — Diff — Docs
All Underscore functions can now be called in an object-oriented style,
like so: _([1, 2, 3]).map(...);. Original patch provided by
Marc-André Cournoyer.
Wrapped objects can be chained through multiple
method invocations. A functions method
was added, providing a sorted list of all the functions in Underscore.
0.3.3 — October 31, 2009 — Diff — Docs
Added the JavaScript 1.8 function reduceRight. Aliased it
as foldr, and aliased reduce as foldl.
0.3.2 — October 29, 2009 — Diff — Docs
Now runs on stock Rhino
interpreters with: load("underscore.js").
Added identity as a utility function.
0.3.1 — October 29, 2009 — Diff — Docs
All iterators are now passed in the original collection as their third
argument, the same as JavaScript 1.6's forEach. Iterating over
objects is now called with (value, key, collection), for details
see _.each.
0.3.0 — October 29, 2009 — Diff — Docs
Added Dmitry Baranovskiy's
comprehensive optimizations, merged in
Kris Kowal's patches to make Underscore
CommonJS and
Narwhal compliant.
0.2.0 — October 28, 2009 — Diff — Docs
Added compose and lastIndexOf, renamed inject to
reduce, added aliases for inject, filter,
every, some, and forEach.
0.1.1 — October 28, 2009 — Diff — Docs
Added noConflict, so that the "Underscore" object can be assigned to
other variables.
0.1.0 — October 28, 2009 — Docs
Initial release of Underscore.js.