Underscore 是一个JavaScript实用库,提供了类似Prototype.js (或 Ruby)的一些功能,但是没有继承任何JavaScript内置对象。它弥补了部分jQuery没有实现的功能,同时又是Backbone.js必不可少的部分。

Underscore提供了80多个函数,包括常用的: map, select, invoke — 当然还有更多专业的辅助函数,如:函数绑定, JavaScript模板功能, 强类型相等测试, 等等. 在新的浏览器中, 有许多函数如果浏览器本身直接支持,将会采用原生的,如 forEach, map, reduce, filter, every, someindexOf.

一个完整的 测试评分 可以给您更详细的对比.

您也可以阅读 带注释的源码.

此项目 在GitHub托管. 您可以在 issues页面报告Bug或者讨论功能, 或者 Freenode 上的 #documentcloud 频道, 或者发推到 @documentcloud.

Underscore 是一个DocumentCloud的开源组件.

下载 (右键单击, 选择 "另存为")

开发版 (1.7.0) 46kb, 未压缩版, 含大量注释
生产版 (1.7.0) 5.2kb, 最简化并用Gzip压缩  (Source Map)
不稳定版 未发布版本, 当前开发中的 master 分支, 如果实用此版本, 风险自负

Installation

集合函数 (数组或对象)

each_.each(list, iterator, [context]) 别名: forEach
对一个 list 的所有元素进行迭代, 对每一个元素执行 iterator 函数. iteratorcontext 对象绑定, 如果传了这个参数. 每次 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
也被称为 injectfoldl, 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]]

Array Functions

注意: 所有数组函数都可以用在 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, "", undefinedNaN 真值检验的结果都为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])
一个灵活创建范围内整数数组的函数, eachmap 循环整合的简便版本. 如果省略start 参数, 默认为 0; step 默认为 1. 返回一个数组, 包含从 startstop (不包含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显示之前返回这个function

throttle_.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格式的评论预览, 当窗口停止改变大小之后重新计算布局, 等等.

传参 immediatetrue 会让 debouncewait 间隔之后 触发最后的函数调用而不是最先的函数调用. 在类似不小心点了提交按钮两下而提交了两次的情况下很有用.

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 call

wrap_.wrap(function, wrapper)
将第一个函数 function 封装到函数 wrapper 里面, 并把函数 function 作为第一个参数传给 wrapper. 这样可以让 wrapperfunction 运行之前和之后 执行代码, 调整参数然后附有条件地执行.

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);
=> 0

compose_.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");
=> true

property_.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);
=> true

matches_.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);
=> true

isEmpty_.isEmpty(object)
如果 object 里没包含任何东西, 将返回 true.

_.isEmpty([1, 2, 3]);
=> false
_.isEmpty({});
=> true

isElement_.isElement(object)
如果 object 是一个DOM元素, 将返回 true.

_.isElement(jQuery('body')[0]);
=> true

isArray_.isArray(object)
如果 object 是一个数组, 将返回 true.

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

isObject_.isObject(value)
如果 value 是一个对象, 将返回 true. 注意在JavaScript中数组和函数都是对象, 而普通的字符串和数字不是.

_.isObject({});
=> true
_.isObject(1);
=> false

isArguments_.isArguments(object)
如果 object 是参数(Arguments)对象, 将返回 true.

(function(){ return _.isArguments(arguments); })(1, 2, 3);
=> true
_.isArguments([1,2,3]);
=> false

isFunction_.isFunction(object)
如果 object 是函数, 将返回 true.

_.isFunction(alert);
=> true

isString_.isString(object)
如果 object 是字符串, 将返回 true.

_.isString("moe");
=> true

isNumber_.isNumber(object)
如果 object 是一个数字(包括NaN), 将返回 true.

_.isNumber(8.4 * 5);
=> true

isFinite_.isFinite(object)
如果 object 是一个有限的数字, 将返回 true.

_.isFinite(-101);
=> true

_.isFinite(-Infinity);
=> false

isBoolean_.isBoolean(object)
如果 object 是布尔值(truefalse), 将返回 true.

_.isBoolean(null);
=> false

isDate_.isDate(object)
如果 object 是时间对象, 将返回 true.

_.isDate(new Date());
=> true

isRegExp_.isRegExp(object)
如果 object 是正则表达式对象, 将返回 true

_.isRegExp(/moe/);
=> true

isNaN_.isNaN(object)
如果 objectNaN, 将返回 true.
注意: 这与原生的 isNaN 函数不一样, 原生的传参即使是 undefined 也会返回true.

_.isNaN(NaN);
=> true
isNaN(undefined);
=> true
_.isNaN(undefined);
=> false

isNull_.isNull(object)
如果 object 的值是 null, 将返回 true.

_.isNull(null);
=> true
_.isNull(undefined);
=> false

isUndefined_.isUndefined(value)
如果 variableundefined, 将会返回 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);
=> true

constant_.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)();
=> true

noop_.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);
=> 42

mixin_.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 &amp; Moe"

unescape_.unescape(string)
The opposite of escape, replaces &amp;, &lt;, &gt;, &quot;, &#96; and &#x27; with their unescaped counterparts.

_.unescape('Curly, Larry &amp; 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();
=> 1392066795351

template_.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>&lt;script&gt;</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]

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.7.0August 26, 2014DiffDocs

  • For consistency and speed across browsers, Underscore now ignores native array methods for forEach, map, reduce, reduceRight, filter, every, some, indexOf, and lastIndexOf. "Sparse" arrays are officially dead in Underscore.
  • Added _.iteratee to customize the iterators used by collection functions. Many Underscore methods will take a string argument for easier _.property-style lookups, an object for _.where-style filtering, or a function as a custom callback.
  • Added _.before as a counterpart to _.after.
  • Added _.negate to invert the truth value of a passed-in predicate.
  • Added _.noop as a handy empty placeholder function.
  • _.isEmpty now works with arguments objects.
  • _.has now guards against nullish objects.
  • _.omit can now take an iteratee function.
  • _.partition is now called with index and object.
  • _.matches creates a shallow clone of your object and only iterates over own properties.
  • Aligning better with the forthcoming ECMA6 Object.assign, _.extend only iterates over the object's own properties.
  • Falsey guards are no longer needed in _.extend and _.defaults—if the passed in argument isn't a JavaScript object it's just returned.
  • Fixed a few edge cases in _.max and _.min to handle arrays containing NaN (like strings or other objects) and Infinity and -Infinity.
  • Override base methods like each and some and they'll be used internally by other Underscore functions too.
  • The escape functions handle backticks (`), to deal with an IE ≤ 8 bug.
  • For consistency, _.union and _.difference now only work with arrays and not variadic args.
  • _.memoize exposes the cache of memoized values as a property on the returned function.
  • _.pick accepts iteratee and context arguments for a more advanced callback.
  • Underscore templates no longer accept an initial data object. _.template always returns a function now.
  • Optimizations and code cleanup aplenty.

1.6.0February 10, 2014DiffDocs

  • Underscore now registers itself for AMD (Require.js), Bower and Component, as well as being a CommonJS module and a regular (Java)Script. An ugliness, but perhaps a necessary one.
  • Added _.partition, a way to split a collection into two lists of results — those that pass and those that fail a particular predicate.
  • Added _.property, for easy creation of iterators that pull specific properties from objects. Useful in conjunction with other Underscore collection functions.
  • Added _.matches, a function that will give you a predicate that can be used to tell if a given object matches a list of specified key/value properties.
  • Added _.constant, as a higher-order _.identity.
  • Added _.now, an optimized way to get a timestamp — used internally to speed up debounce and throttle.
  • The _.partial function may now be used to partially apply any of its arguments, by passing _ wherever you'd like a placeholder variable, to be filled-in later.
  • The _.each function now returns a reference to the list for chaining.
  • The _.keys function now returns an empty array for non-objects instead of throwing.
  • … and more miscellaneous refactoring.

1.5.2September 7, 2013DiffDocs

  • Added an indexBy function, which fits in alongside its cousins, countBy and groupBy.
  • Added a sample function, for sampling random elements from arrays.
  • Some optimizations relating to functions that can be implemented in terms of _.keys (which includes, significantly, each on objects). Also for debounce in a tight loop.

1.5.1July 8, 2013DiffDocs

  • Removed unzip, as it's simply the application of zip to an array of arguments. Use _.zip.apply(_, list) to transpose instead.

1.5.0July 6, 2013DiffDocs

  • Added a new unzip function, as the inverse of _.zip.
  • The throttle function now takes an options argument, allowing you to disable execution of the throttled function on either the leading or trailing edge.
  • A source map is now supplied for easier debugging of the minified production build of Underscore.
  • The defaults function now only overrides undefined values, not null ones.
  • Removed the ability to call _.bindAll with no method name arguments. It's pretty much always wiser to white-list the names of the methods you'd like to bind.
  • Removed the ability to call _.after with an invocation count of zero. The minimum number of calls is (naturally) now 1.

1.4.4January 30, 2013DiffDocs

  • Added _.findWhere, for finding the first element in a list that matches a particular set of keys and values.
  • Added _.partial, for partially applying a function without changing its dynamic reference to this.
  • Simplified bind by removing some edge cases involving constructor functions. In short: don't _.bind your constructors.
  • A minor optimization to invoke.
  • Fix bug in the minified version due to the minifier incorrectly optimizing-away isFunction.

1.4.3December 4, 2012DiffDocs

  • Improved Underscore compatibility with Adobe's JS engine that can be used to script Illustrator, Photoshop, and friends.
  • Added a default _.identity iterator to countBy and groupBy.
  • The uniq function can now take array, iterator, context as the argument list.
  • The times function now returns the mapped array of iterator results.
  • Simplified and fixed bugs in throttle.

1.4.2October 6, 2012DiffDocs

  • For backwards compatibility, returned to pre-1.4.0 behavior when passing null to iteration functions. They now become no-ops again.

1.4.1October 1, 2012DiffDocs

  • Fixed a 1.4.0 regression in the lastIndexOf function.

1.4.0September 27, 2012DiffDocs

  • Added a pairs function, for turning a JavaScript object into [key, value] pairs ... as well as an object function, for converting an array of [key, value] pairs into an object.
  • Added a countBy function, for counting the number of objects in a list that match a certain criteria.
  • Added an invert function, for performing a simple inversion of the keys and values in an object.
  • Added a where function, for easy cases of filtering a list for objects with specific values.
  • Added an omit function, for filtering an object to remove certain keys.
  • Added a random function, to return a random number in a given range.
  • _.debounce'd functions now return their last updated value, just like _.throttle'd functions do.
  • The sortBy function now runs a stable sort algorithm.
  • Added the optional fromIndex option to indexOf and lastIndexOf.
  • "Sparse" arrays are no longer supported in Underscore iteration functions. Use a for loop instead (or better yet, an object).
  • The min and max functions may now be called on very large arrays.
  • Interpolation in templates now represents null and undefined as the empty string.
  • Underscore iteration functions no longer accept null values as a no-op argument. You'll get an early error instead.
  • A number of edge-cases fixes and tweaks, which you can spot in the diff. Depending on how you're using Underscore, 1.4.0 may be more backwards-incompatible than usual — please test when you upgrade.

1.3.3April 10, 2012DiffDocs

  • Many improvements to _.template, which now provides the source of the template function as a property, for potentially even more efficient pre-compilation on the server-side. You may now also set the variable option when creating a template, which will cause your passed-in data to be made available under the variable you named, instead of using a with statement — significantly improving the speed of rendering the template.
  • Added the pick function, which allows you to filter an object literal with a whitelist of allowed property names.
  • Added the result function, for convenience when working with APIs that allow either functions or raw properties.
  • Added the isFinite function, because sometimes knowing that a value is a number just ain't quite enough.
  • The sortBy function may now also be passed the string name of a property to use as the sort order on each object.
  • Fixed uniq to work with sparse arrays.
  • The difference function now performs a shallow flatten instead of a deep one when computing array differences.
  • The debounce function now takes an immediate parameter, which will cause the callback to fire on the leading instead of the trailing edge.

1.3.1January 23, 2012DiffDocs

  • Added an _.has function, as a safer way to use hasOwnProperty.
  • Added _.collect as an alias for _.map. Smalltalkers, rejoice.
  • Reverted an old change so that _.extend will correctly copy over keys with undefined values again.
  • Bugfix to stop escaping slashes within interpolations in _.template.

1.3.0January 11, 2012DiffDocs

  • Removed AMD (RequireJS) support from Underscore. If you'd like to use Underscore with RequireJS, you can load it as a normal script, wrap or patch your copy, or download a forked version.

1.2.4January 4, 2012DiffDocs

  • You now can (and probably should, as it's simpler) write _.chain(list) instead of _(list).chain().
  • Fix for escaped characters in Underscore templates, and for supporting customizations of _.templateSettings that only define one or two of the required regexes.
  • Fix for passing an array as the first argument to an _.wrap'd function.
  • Improved compatibility with ClojureScript, which adds a call function to String.prototype.

1.2.3December 7, 2011DiffDocs

  • Dynamic scope is now preserved for compiled _.template functions, so you can use the value of this if you like.
  • Sparse array support of _.indexOf, _.lastIndexOf.
  • Both _.reduce and _.reduceRight can now be passed an explicitly undefined value. (There's no reason why you'd want to do this.)

1.2.2November 14, 2011DiffDocs

  • Continued tweaks to _.isEqual semantics. Now JS primitives are considered equivalent to their wrapped versions, and arrays are compared by their numeric properties only (#351).
  • _.escape no longer tries to be smart about not double-escaping already-escaped HTML entities. Now it just escapes regardless (#350).
  • In _.template, you may now leave semicolons out of evaluated statements if you wish: <% }) %> (#369).
  • _.after(callback, 0) will now trigger the callback immediately, making "after" easier to use with asynchronous APIs (#366).

1.2.1October 24, 2011DiffDocs

  • Several important bug fixes for _.isEqual, which should now do better on mutated Arrays, and on non-Array objects with length properties. (#329)
  • James Burke contributed Underscore exporting for AMD module loaders, and Tony Lukasavage for Appcelerator Titanium. (#335, #338)
  • You can now _.groupBy(list, 'property') as a shortcut for grouping values by a particular common property.
  • _.throttle'd functions now fire immediately upon invocation, and are rate-limited thereafter (#170, #266).
  • Most of the _.is[Type] checks no longer ducktype.
  • The _.bind function now also works on constructors, a-la ES5 ... but you would never want to use _.bind on a constructor function.
  • _.clone no longer wraps non-object types in Objects.
  • _.find and _.filter are now the preferred names for _.detect and _.select.

1.2.0October 5, 2011DiffDocs

  • The _.isEqual function now supports true deep equality comparisons, with checks for cyclic structures, thanks to Kit Cambridge.
  • Underscore templates now support HTML escaping interpolations, using <%- ... %> syntax.
  • Ryan Tenney contributed _.shuffle, which uses a modified Fisher-Yates to give you a shuffled copy of an array.
  • _.uniq can now be passed an optional iterator, to determine by what criteria an object should be considered unique.
  • _.last now takes an optional argument which will return the last N elements of the list.
  • A new _.initial function was added, as a mirror of _.rest, which returns all the initial values of a list (except the last N).

1.1.7July 13, 2011DiffDocs
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.6April 18, 2011DiffDocs
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.5March 20, 2011DiffDocs
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.4January 9, 2011DiffDocs
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.3December 1, 2010DiffDocs
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.2October 15, 2010DiffDocs
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.1October 5, 2010DiffDocs
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.0August 18, 2010DiffDocs
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.4June 22, 2010DiffDocs
Andri Möll contributed the _.memoize function, which can be used to speed up expensive repeated computations by caching the results.

1.0.3June 14, 2010DiffDocs
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.2March 23, 2010DiffDocs
Fixes _.isArguments in recent versions of Opera, which have arguments objects as real Arrays.

1.0.1March 19, 2010DiffDocs
Bugfix for _.isEqual, when comparing two objects with the same number of undefined keys, but with different names.

1.0.0March 18, 2010DiffDocs
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.0February 24, 2010DiffDocs
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.8January 28, 2010DiffDocs
Fixed Underscore's collection functions to work on NodeLists and HTMLCollections once more, thanks to Justin Tulloss.

0.5.7January 20, 2010DiffDocs
A safer implementation of _.isArguments, and a faster _.isNumber,
thanks to Jed Schmidt.

0.5.6January 18, 2010DiffDocs
Customizable delimiters for _.template, contributed by Noah Sloan.

0.5.5January 9, 2010DiffDocs
Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.

0.5.4January 5, 2010DiffDocs
Fix for multiple single quotes within a template string for _.template. See: Rick Strahl's blog post.

0.5.2January 1, 2010DiffDocs
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.1December 9, 2009DiffDocs
Added an _.isArguments function. Lots of little safety checks and optimizations contributed by Noah Sloan and Andri Möll.

0.5.0December 7, 2009DiffDocs
[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.7December 6, 2009DiffDocs
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.6November 30, 2009DiffDocs
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.5November 19, 2009DiffDocs
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.4November 18, 2009DiffDocs
Added isString, and isNumber, for consistency. Fixed _.isEqual(NaN, NaN) to return true (which is debatable).

0.4.3November 9, 2009DiffDocs
Started using the native StopIteration object in browsers that support it. Fixed Underscore setup for CommonJS environments.

0.4.2November 9, 2009DiffDocs
Renamed the unwrapping function to value, for clarity.

0.4.1November 8, 2009DiffDocs
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.0November 7, 2009DiffDocs
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.3October 31, 2009DiffDocs
Added the JavaScript 1.8 function reduceRight. Aliased it as foldr, and aliased reduce as foldl.

0.3.2October 29, 2009DiffDocs
Now runs on stock Rhino interpreters with: load("underscore.js"). Added identity as a utility function.

0.3.1October 29, 2009DiffDocs
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.0October 29, 2009DiffDocs
Added Dmitry Baranovskiy's comprehensive optimizations, merged in Kris Kowal's patches to make Underscore CommonJS and Narwhal compliant.

0.2.0October 28, 2009DiffDocs
Added compose and lastIndexOf, renamed inject to reduce, added aliases for inject, filter, every, some, and forEach.

0.1.1October 28, 2009DiffDocs
Added noConflict, so that the "Underscore" object can be assigned to other variables.

0.1.0October 28, 2009Docs
Initial release of Underscore.js.

A DocumentCloud Project