Underscore.js是一个很精干的库,压缩后只有4KB。它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程。MVC框架Backbone.js就将这个库作为自己的工具库。除了可以在浏览器环境使用,Underscore.js还可以用于Node.js。
Underscore.js定义了一个下划线(_)对象,函数库的所有方法都属于这个对象。这些方法大致上可以分成:集合(collection)、数组(array)、函数(function)、对象(object)和工具(utility)五大类。
nderscore is a JavaScript library that provides a whole mess of 一大堆useful functional programming helpers without extending any built-in objects. It’s the answer to the question: “If I sit down in front of a blank HTML page, and want to start being productive immediately, what do I need?” … and the tie to go along with jQuery‘s tux andBackbone‘s suspenders.
Underscore provides 80-odd 80左右functions that support both the usual functional suspects:map, select, invoke — as well as more specialized helpers: function binding, javascript templating, deep equality testing, and so on. It delegates to built-in functions, if present, so modern browsers will use the native implementations of forEach, map,reduce, filter, every, some and indexOf.
A complete Test & Benchmark Suite is included for your perusal.
Underscore提供的60多个函数:
http://www.css88.com/doc/underscore/
部分函数:
Collections(集合)
each, map, reduce, reduceRight, find, filter, reject, all, any, include, invoke,pluck, max, min, sortBy, groupBy, sortedIndex, shuffle, toArray, size
Arrays(数组)
first, initial, last, rest, compact, flatten, without, union, intersection,difference, uniq, zip, indexOf, lastIndexOf, range
Functions(函数)
bind, bindAll, memoize, delay, defer, throttle, debounce, once, after, wrap,compose
Objects(对象)
keys, values, functions, extend, defaults, clone, tap, isEqual, isEmpty,isElement, isArray, isArguments, isFunction, isString, isNumber, isBoolean,isDate, isRegExp, isNaN, isNull, isUndefined
Utility(功能)
noConflict, identity, times, mixin, uniqueId, escape, template
Collection Functions (Arrays or Objects)
英文:
中文翻译:http://www.css88.com/doc/underscore/
each_.each(list, iterator,
[context])
Alias: forEach
Iterates over
a list of elements, yielding each in turn to
an iterator function.
Theiterator is bound to
the context object, if one is passed. Each invocation
of iterator is called with three
arguments: (element, index, list).
If list is a JavaScript
object,iterator‘s arguments will be (value, key,
list). Delegates to the native forEachfunction if it
exists, and returns the original list for
chaining.
_.each([1, 2, 3], alert); => alerts each number in turn... _.each({one: 1, two: 2, three: 3}, alert); => alerts each number value in turn...
Note: Collection functions work on arrays, objects, and array-like objects such asarguments, 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])
Alias: collect
通过变换函数(iterator迭代器)把list中的每个值映射到一个新的数组中(愚人码头注:产生一个新的数组)。如果存在原生的map方法,就用原生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])
Aliases: inject,
foldl
别名为 inject 和 foldl, reduce方法把list中元素归结为一个单独的数值。Memo是reduce函数的初始值,reduce的每一步都需要由iterator返回。这个迭代传递4个参数: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])
Alias: foldr
reducRight是从右侧开始组合的元素的reduce函数,如果存在JavaScript
1.8版本的reduceRight,则用其代替。Foldr在javascript中不像其它有懒计算的语言那么有用(lazy
evaluation:一种求值策略,只有当表达式的值真正需要时才对表达式进行计算)。
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])
Alias: detect
遍历list,返回第一个通过iterator迭代器真值检测的元素值,如果没有值传递给测试迭代器将返回undefined
。 如果找到匹配的元素,函数将立即返回,不会遍历整个list。
var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => 2
filter_.filter(list,
iterator, [context])
Alias: select
遍历list中的每个值,返回包含所有通过iterator真值检测的元素值。如果存在原生filter方法,则用原生的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所列出的属性的所有的键
- 值对。
_.where(listOfPlays, {author: "Shakespeare", year: 1611}); => [{title: "Cymbeline", author: "Shakespeare", year: 1611}, {title: "The Tempest", author: "Shakespeare", year: 1611}]
findWhere_.findWhere(list,
properties)
遍历list中的每一个值,返回匹配properties所列出的属性的所有的键
- 值对的第一个值。
如果没有找到匹配的属性,或者list是空的,那么将返回undefined。
_.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]
对象相关方法
toArray方法将对象转为数组,只包含对象成员的值。典型应用是将对类似数组的对象转为真正的数组。
_.toArray({a:0,b:1,c:2});
// [0, 1, 2]
pluck方法将多个对象的某一个属性的值,提取成一个数组。
var stooges = [{name : ‘moe‘, age : 40}, {name : ‘larry‘, age : 50}, {name : ‘curly‘, age : 60}];
_.pluck(stooges, ‘name‘);
// ["moe", "larry", "curly"]
与函数相关的方法
绑定运行环境和参数
在不同的运行环境下,JavaScript函数内部的变量所在的上下文是不同的。这种特性会给程序带来不确定性,为了解决这个问题,Underscore.js提供了两个方法,用来给函数绑定上下文。
(1)bind方法
该方法绑定函数运行时的上下文,返回一个新函数。
bind_.bind(function, object,
*arguments)
Bind a function to
an object, meaning that whenever the function is called,
the value of this will be the object.
Optionally, pass arguments to
the function to pre-fill them, also known
as partial application.
var func = function(greeting){ return greeting + ‘: ‘ + this.name };
func = _.bind(func, {name: ‘moe‘}, ‘hi‘);
func();
=> ‘hi: moe‘
bindAll_.bindAll(object,
*methodNames)
Binds a number of methods on
the object, specified
by methodNames, to be run in the context of that object
whenever they are invoked. Very handy for binding functions that are going to be
used as event handlers, which would otherwise be invoked with a fairly
useless this. methodNames are
required.
var buttonView = {
label : ‘underscore‘,
onClick: function(){ alert(‘clicked: ‘ + this.label); },
onHover: function(){ console.log(‘hovering: ‘ + this.label); }
};
_.bindAll(buttonView, ‘onClick‘, ‘onHover‘);
// When the button is clicked, this.label will have the correct value.
jQuery(‘#underscore_button‘).bind(‘click‘, buttonView.onClick);
var o = {
p: 2,
m: function (){console.log(this.p);}
};
o.m()
// 2
_.bind(o.m,{p:1})()
// 1
上面代码将o.m方法绑定到一个新的对象上面。
除了前两个参数以外,bind方法还可以接受更多参数,它们表示函数方法运行时所需的参数。
var add = function(n1,n2,n3) {
console.log(this.sum + n1 + n2 + n3);
};
_.bind(add, {sum:1}, 1, 1, 1)()
// 4
上面代码中bind方法有5个参数,最后那三个是给定add方法的运行参数,所以运行结果为4。
2)bindall方法
该方法可以一次将多个方法,绑定在某个对象上面。
var o = {
p1 : ‘123‘,
p2 : ‘456‘,
m1 : function() { console.log(this.p1); },
m2 : function() { console.log(this.p2); },
};
_.bindAll(o, ‘m1‘, ‘m2‘);
上面代码一次性将两个方法(m1和m2)绑定在o对象上面。
(3)partial方法
除了绑定上下文,Underscore.js还允许绑定参数。partial方法将函数与某个参数绑定,然后作为一个新函数返回。
var add = function(a, b) { return a + b; };
add5 = _.partial(add, 5);
add5(10);
// 15
(4)wrap方法
该方法将一个函数作为参数,传入另一个函数,最终返回前者的一个新版本。
var hello = function(name) { return "hello: " + name; };
hello = _.wrap(hello, function(func) {
return "before, " + func("moe") + ", after";
});
hello();
// ‘before, hello: moe, after‘
上面代码先定义hello函数,然后将hello传入一个匿名定义,返回一个新版本的hello函数。
(5)compose方法
该方法接受一系列函数作为参数,由后向前依次运行,上一个函数的运行结果,作为后一个函数的运行参数。也就是说,将f(g(),h())的形式转化为f(g(h()))。
var greet = function(name){ return "hi: " + name; };
var exclaim = function(statement){ return statement + "!"; };
var welcome = _.compose(exclaim, greet);
welcome(‘moe‘);
// ‘hi: moe!‘
上面代码调用welcome时,先运行greet函数,再运行exclaim函数。并且,greet函数的运行结果是exclaim函数运行时的参数。