跳转到内容
新建笔记

underscore

Array有map()和filter()方法,可是Object没有这些方法。此外,低版本的浏览器例如IE6~8也没有这些方法,怎么办?

方法一,自己把这些方法添加到Array.prototype中,然后给Object.prototype也加上mapObject()等类似的方法。

方法二,直接找一个成熟可靠的第三方开源库,使用统一的函数来实现map()、filter()这些操作。

underscore则提供了一套完善的函数式编程的接口,让我们更方便地在JavaScript中实现函数式编程。

jQuery在加载时,会把自身绑定到唯一的全局变量$上,underscore与其类似,会把自身绑定到唯一的全局变量_上,这也是为啥它的名字叫underscore的原因。

Collections

underscore为集合类对象提供了一致的接口。集合类是指Array和Object,暂不支持Map和Set。

函数说明代码示例
map对集合中的每个元素应用给定函数,返回新数组_.map([1, 2, 3], x => x * 2); // [2, 4, 6]
filter根据给定函数测试条件,返回符合条件的新数组_.filter([1, 2, 3, 4], x => x > 2); // [3, 4]
every检查集合是否所有元素都满足给定函数条件_.every([1, 2, 3], x => x > 0); // true
some检查集合是否至少有一个元素满足给定函数条件_.some([1, 2, 3], x => x > 2); // true
max / min分别返回集合中的最大值和最小值_.max([1, 2, 3]); // 3
_.min([1, 2, 3]); // 1
groupBy根据给定函数对集合进行分组_.groupBy([1.3, 2.1, 2.4], x => Math.floor(x)); // { '1': [1.3], '2': [2.1, 2.4] }
shuffle / sample分别用于打乱集合顺序和随机选择元素_.shuffle([1, 2, 3]);
_.sample([1, 2, 3], 2);

Array

underscore为Array提供了许多工具类方法,可以更方便快捷地操作Array。

序号函数名说明代码示例
1first取数组的第一个元素_.first([2, 4, 6, 8]); // 2
2last取数组的最后一个元素_.last([2, 4, 6, 8]); // 8
3flatten将嵌套数组变成一维数组_.flatten([1, [2], [3, [[4], [5]]]]); // [1, 2, 3, 4, 5]
4zip将多个数组的元素按索引对齐并合并成新数组_.zip([‘Adam’, ‘Lisa’, ‘Bart’], [85, 92, 59]); // [[‘Adam’, 85], [‘Lisa’, 92], [‘Bart’, 59]]
5unzip将由数组组成的数组转换为数组的数组_.unzip([[‘Adam’, 85], [‘Lisa’, 92], [‘Bart’, 59]]) // [[‘Adam’, ‘Lisa’, ‘Bart’], [85, 92, 59]]
6object将两个数组转换为对象,其中第一个数组的元素作为键,第二个数组的元素作为值_.object([‘Adam’, ‘Lisa’, ‘Bart’], [85, 92, 59]); // {Adam: 85, Lisa: 92, Bart: 59}
7range生成一个序列_.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Functions

因为underscore本来就是为了充分发挥JavaScript的函数式编程特性,所以也提供了大量JavaScript本身没有的高阶函数。

函数说明代码示例
bind绑定函数的this上下文和参数_.bind(console.log, console, 'Hello')(); // 'Hello'
partial创建一个偏函数,固定原函数的某些参数_.partial(Math.pow, 2)(5); // 32
memoize缓存函数的结果,避免重复计算let fib = _.memoize(n => { /* 计算斐波那契数 */ });
once确保函数只执行一次let greet = _.once(() => console.log('Hello!'));
delay延迟函数的执行_.delay(alert, 1000, 'Hello after 1 second!');

Objects

和Array类似,underscore也提供了大量针对Object的函数。

函数说明代码示例
keys / allKeys分别返回对象自身的和包含原型链上的所有键_.keys({a: 1, b: 2}); // ['a', 'b']
_.allKeys(xiaoming);
values返回对象自身的所有值_.values({a: 1, b: 2}); // [1, 2]
mapObject对象的map操作_.mapObject({a: 1, b: 2}, (v, k) => v * 2); // { a: 2, b: 4 }
invert交换对象的键值对_.invert({Adam: 90, Lisa: 85}); // { '90': 'Adam', '85': 'Lisa' }
extend / extendOwn分别用于浅复制和浅复制并忽略原型链的属性_.extend({}, {a: 1}, {b: 2}); // {a: 1, b: 2}
clone浅复制对象_.clone({a: 1, b: 2}); // {a: 1, b: 2}
isEqual深度比较两个对象是否相等_.isEqual({a: 1, b: 2}, {a: 1, b: 2}); // true

Chaining

函数说明代码示例
chain开始一个链式调用_.chain([1, 2, 3]).map(x => x * 2).value(); // [2, 4, 6]
let r = _.chain([1, 4, 9, 16, 25])
.map(Math.sqrt)
.filter(x => x % 2 === 1)
.value();
console.log(r); // [1, 3, 5]