Javascript工具库Underscore

  1 Underscore.js
  2 
  3 Underscore 是一个 JavaScript 工具库,它提供了一整套函数式编程的实用功能,可是没有扩展任何 JavaScript 内置对象。 他解决了这个问题:“若是我面对一个空白的 HTML 页面,并但愿当即开始工做,我须要什么?” 他弥补了 jQuery 没有实现的功能,同时又是 Backbone 必不可少的部分。
  4 
  5 Underscore 提供了100多个函数,包括经常使用的:map、filter、invoke — 固然还有更多专业的辅助函数,如:函数绑定、JavaScript 模板功能、建立快速索引、强类型相等测试等等。
  6 
  7 为了你能仔细研读,这里包含了一个完整的测试套件。
  8 
  9 你还能够通读带有注释的源码。
 10 
 11 享受 Underscore 所带来的便利吧。若是你但愿得到更多有用的功能,能够试试 Underscore-contrib。
 12 
 13 本项目 托管在 GitHub 上。 你能够在 issues page 或 Freenode 上的 #documentcloud 频道内报告 bug 以及参与特性讨论。
 14 
 15 Underscore 是 DocumentCloud 的一个开源组件。
 16 下载 (点击右键“另存为”)
 17 开发版本 (1.7.0)     46kb,未压缩,包含大量注释
 18 生产环境版本 (1.7.0)     5.2kb,去除注释并压缩  (Source Map)
 19 不稳定版本     不发布,当前 master 代码分支,风险自负。
 20 安装
 21 
 22     Node.js npm install underscore
 23     Meteor.js meteor add underscore
 24     Require.js require(["underscore"], ...
 25     Bower bower install underscore
 26     Component component install jashkenas/underscore
 27 
 28 稽核函数(数组或对象)
 29 
 30 each_.each(list, iteratee, [context]) 别名: forEach
 31 遍历list中的全部元素,按顺序用遍历输出每一个元素。若是传递了context参数,则把iteratee绑定到context对象上。每次调用iteratee都会传递三个参数:(element, index, list)。若是list是个JavaScript对象,iteratee的参数是 (value, key, list))。返回list以方便链式调用。(注:若是存在原生的forEach方法,Underscore就使用它代替。)
 32 
 33 _.each([1, 2, 3], alert);
 34 => alerts each number in turn...
 35 _.each({one: 1, two: 2, three: 3}, alert);
 36 => alerts each number value in turn...
 37 
 38 注意:集合函数能在数组,对象,和类数组对象,好比arguments, NodeList和相似的数据类型上正常工做。 可是它经过鸭子类型工做,因此要避免传递一个不固定length属性的对象(注:对象或数组的长度(length)属性要固定的)。每一个循环不能被破坏 - 打破, 使用_.find代替,这也是很好的注意。
 39 
 40 map_.map(list, iteratee, [context]) 别名: collect
 41 经过变换函数(iteratee迭代器)把list中的每一个值映射到一个新的数组中(注:产生一个新的数组)。若是存在原生的map方法,就用原生map方法来代替。若是list是个JavaScript对象,iteratee的参数是(value, key, list)。
 42 
 43 _.map([1, 2, 3], function(num){ return num * 3; });
 44 => [3, 6, 9]
 45 _.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
 46 => [3, 6, 9]
 47 
 48 reduce_.reduce(list, iteratee, [memo], [context]) Aliases: inject, foldl
 49 别名为 inject 和 foldl, reduce方法把list中元素归结为一个单独的数值。Memo是reduce函数的初始值,reduce的每一步都须要由iteratee返回。这个迭代传递4个参数:memo, value 和 迭代的index(或者 key)和最后一个引用的整个 list。
 50 
 51 若是没有memo传递给reduce的初始调用,iteratee不会被列表中的第一个元素调用。第一个元素将取代 传递给列表中下一个元素调用iteratee的memo参数,
 52 
 53 var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
 54 => 6
 55 
 56 reduceRight_.reduceRight(list, iteratee, memo, [context]) 别名: foldr
 57 reducRight是从右侧开始组合的元素的reduce函数,若是存在JavaScript 1.8版本的reduceRight,则用其代替。Foldr在javascript中不像其它有懒计算的语言那么有用(注:lazy evaluation:一种求值策略,只有当表达式的值真正须要时才对表达式进行计算)。
 58 
 59 var list = [[0, 1], [2, 3], [4, 5]];
 60 var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
 61 => [4, 5, 2, 3, 0, 1]
 62 
 63 find_.find(list, predicate, [context]) 别名: detect
 64 在list中逐项查找,返回第一个经过predicate迭代函数真值检测的元素值,若是没有值传递给测试迭代器将返回undefined。 若是找到匹配的元素,函数将当即返回,不会遍历整个list。
 65 
 66 var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 67 => 2
 68 
 69 filter_.filter(list, predicate, [context]) 别名: select
 70 遍历list中的每一个值,返回包含全部经过predicate真值检测的元素值。(注:若是存在原生filter方法,则用原生的filter方法。)
 71 
 72 var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 73 => [2, 4, 6]
 74 
 75 where_.where(list, properties)
 76 遍历list中的每个值,返回一个数组,这个数组包含包含properties所列出的属性的全部的键 - 值对。
 77 
 78 _.where(listOfPlays, {author: "Shakespeare", year: 1611});
 79 => [{title: "Cymbeline", author: "Shakespeare", year: 1611},
 80     {title: "The Tempest", author: "Shakespeare", year: 1611}]
 81 
 82 findWhere_.findWhere(list, properties)
 83 遍历list中的每个值,返回匹配properties所列出的属性的全部的键 - 值对的第一个值。
 84 
 85 若是没有找到匹配的属性,或者list是空的,那么将返回undefined。
 86 
 87 _.findWhere(publicServicePulitzers, {newsroom: "The New York Times"});
 88 => {year: 1918, newsroom: "The New York Times",
 89   reason: "For its public service in publishing in full so many official reports,
 90   documents and speeches by European statesmen relating to the progress and
 91   conduct of the war."}
 92 
 93 reject_.reject(list, predicate, [context])
 94 返回list中没有经过predicate真值检测的元素集合,与filter相反。
 95 
 96 var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 97 => [1, 3, 5]
 98 
 99 every_.every(list, [predicate], [context]) 别名: all
100 若是list中的全部元素都经过predicate的真值检测就返回true。(注:若是存在原生的every方法,就使用原生的every。)
101 
102 _.every([true, 1, null, 'yes'], _.identity);
103 => false
104 
105 some_.some(list, [predicate], [context]) 别名: any
106 若是list中有任何一个元素经过 predicate 的真值检测就返回true。一旦找到了符合条件的元素, 就直接中断对list的遍历. (注:若是存在原生的some方法,就使用原生的some。)
107 
108 _.some([null, 0, 'yes', false]);
109 => true
110 
111 contains_.contains(list, value) 别名: include
112 若是list包含指定的value则返回true(注:使用===检测)。若是list 是数组,内部使用indexOf判断。
113 
114 _.contains([1, 2, 3], 3);
115 => true
116 
117 invoke_.invoke(list, methodName, *arguments)
118 在list的每一个元素上执行methodName方法。 任何传递给invoke的额外参数,invoke都会在调用methodName方法的时候传递给它。
119 
120 _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
121 => [[1, 5, 7], [1, 2, 3]]
122 
123 pluck_.pluck(list, propertyName)
124 pluck也许是map最常使用的用例模型的简化版本,即萃取对象数组中某属性值,返回一个数组。
125 
126 var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
127 _.pluck(stooges, 'name');
128 => ["moe", "larry", "curly"]
129 
130 max_.max(list, [iteratee], [context])
131 返回list中的最大值。若是传递iteratee参数,iteratee将做为list中每一个值的排序依据。若是list为空,将返回-Infinity,因此你可能须要事先用isEmpty检查 list 。
132 
133 var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
134 _.max(stooges, function(stooge){ return stooge.age; });
135 => {name: 'curly', age: 60};
136 
137 min_.min(list, [iteratee], [context])
138 返回list中的最小值。若是传递iteratee参数,iteratee将做为list中每一个值的排序依据。若是list为空,将返回-Infinity,因此你可能须要事先用isEmpty检查 list 。
139 
140 var numbers = [10, 5, 100, 2, 1000];
141 _.min(numbers);
142 => 2
143 
144 sortBy_.sortBy(list, iteratee, [context])
145 返回一个排序后的list拷贝副本。若是传递iteratee参数,iteratee将做为list中每一个值的排序依据。迭代器也能够是字符串的属性的名称进行排序的(好比 length)。
146 
147 _.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
148 => [5, 4, 6, 3, 1, 2]
149 
150 groupBy_.groupBy(list, iteratee, [context])
151 把一个集合分组为多个集合,经过 iterator 返回的结果进行分组. 若是 iterator 是一个字符串而不是函数, 那么将使用 iterator 做为各元素的属性名来对比进行分组.
152 
153 _.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
154 => {1: [1.3], 2: [2.1, 2.4]}
155 
156 _.groupBy(['one', 'two', 'three'], 'length');
157 => {3: ["one", "two"], 5: ["three"]}
158 
159 indexBy_.indexBy(list, iteratee, [context])
160 给定一个list,和 一个用来返回一个在列表中的每一个元素键 的iterator 函数(或属性名), 返回一个每一项索引的对象。和groupBy很是像,可是当你知道你的键是惟一的时候可使用indexBy 。
161 
162 var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
163 _.indexBy(stooges, 'age');
164 => {
165   "40": {name: 'moe', age: 40},
166   "50": {name: 'larry', age: 50},
167   "60": {name: 'curly', age: 60}
168 }
169 
170 countBy_.countBy(list, iteratee, [context])
171 排序一个列表组成一个组,而且返回各组中的对象的数量的计数。相似groupBy,可是不是返回列表的值,而是返回在该组中值的数目。
172 
173 _.countBy([1, 2, 3, 4, 5], function(num) {
174   return num % 2 == 0 ? 'even': 'odd';
175 });
176 => {odd: 3, even: 2}
177 
178 shuffle_.shuffle(list)
179 返回一个随机乱序的 list 副本, 使用 Fisher-Yates shuffle 来进行随机乱序.
180 
181 _.shuffle([1, 2, 3, 4, 5, 6]);
182 => [4, 1, 6, 3, 5, 2]
183 
184 sample_.sample(list, [n])
185 从 list中产生一个随机样本。传递一个数字表示从list中返回n个随机元素。不然将返回一个单一的随机项。
186 
187 _.sample([1, 2, 3, 4, 5, 6]);
188 => 4
189 
190 _.sample([1, 2, 3, 4, 5, 6], 3);
191 => [1, 6, 2]
192 
193 toArray_.toArray(list)
194 把list(任何能够迭代的对象)转换成一个数组,在转换 arguments 对象时很是有用。
195 
196 (function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
197 => [2, 3, 4]
198 
199 size_.size(list)
200 返回list的长度。
201 
202 _.size({one: 1, two: 2, three: 3});
203 => 3
204 
205 partition_.partition(array, predicate)
206 拆分一个数组(array)为两个数组: 第一个数组其元素都知足predicate迭代函数, 而第二个的全部元素均不能知足predicate迭代函数。
207 
208 _.partition([0, 1, 2, 3, 4, 5], isOdd);
209 => [[1, 3, 5], [0, 2, 4]]
210 
211 数组函数(Array Functions)
212 
213 注: arguments(参数) 对象将在全部数组函数中工做 。然而, Underscore 函数的设计并不仅是针对稀疏("sparse" )数组的.
214 
215 first_.first(array, [n]) 别名: head, take
216 返回array(数组)的第一个元素。传递 n参数将返回数组中从第一个元素开始的n个元素(注:返回数组中前 n 个元素.)。
217 
218 _.first([5, 4, 3, 2, 1]);
219 => 5
220 
221 initial_.initial(array, [n])
222 返回数组中除了最后一个元素外的其余所有元素。 在arguments对象上特别有用。传递 n参数将从结果中排除从最后一个开始的n个元素(注:排除数组后面的 n 个元素)。
223 
224 _.initial([5, 4, 3, 2, 1]);
225 => [5, 4, 3, 2]
226 
227 last_.last(array, [n])
228 返回array(数组)的最后一个元素。传递 n参数将返回数组中从最后一个元素开始的n个元素(注:返回数组里的后面的n个元素)。
229 
230 _.last([5, 4, 3, 2, 1]);
231 => 1
232 
233 rest_.rest(array, [index]) 别名: tail, drop
234 返回数组中除了第一个元素外的其余所有元素。传递 index 参数将返回从index开始的剩余全部元素 。(感谢@德德德德撸 指出错误)
235 
236 _.rest([5, 4, 3, 2, 1]);
237 => [4, 3, 2, 1]
238 
239 compact_.compact(array)
240 返回一个除去全部false值的 array副本。 在javascript中, false, null, 0, "", undefined 和 NaN 都是false值.
241 
242 _.compact([0, 1, false, 2, '', 3]);
243 => [1, 2, 3]
244 
245 flatten_.flatten(array, [shallow])
246 将一个嵌套多层的数组 array(数组) (嵌套能够是任何层数)转换为只有一层的数组。 若是你传递 shallow参数,数组将只减小一维的嵌套。
247 
248 _.flatten([1, [2], [3, [[4]]]]);
249 => [1, 2, 3, 4];
250 
251 _.flatten([1, [2], [3, [[4]]]], true);
252 => [1, 2, 3, [[4]]];
253 
254 without_.without(array, *values)
255 返回一个删除全部values值后的 array副本。(注:使用===表达式作相等测试。)
256 
257 _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
258 => [2, 3, 4]
259 
260 union_.union(*arrays)
261 返回传入的 arrays(数组)并集:按顺序返回,返回数组的元素是惟一的,能够传入一个或多个 arrays(数组)。
262 
263 _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
264 => [1, 2, 3, 101, 10]
265 
266 intersection_.intersection(*arrays)
267 返回传入 arrays(数组)交集。结果中的每一个值是存在于传入的每一个arrays(数组)里。
268 
269 _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
270 => [1, 2]
271 
272 difference_.difference(array, *others)
273 相似于without,但返回的值来自array参数数组,而且不存在于other 数组.
274 
275 _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
276 => [1, 3, 4]
277 
278 uniq_.uniq(array, [isSorted], [iteratee]) 别名: unique
279 返回 array去重后的副本, 使用 === 作相等测试. 若是您肯定 array 已经排序, 那么给 isSorted 参数传递 true值, 此函数将运行的更快的算法. 若是要处理对象元素, 传参 iterator 来获取要对比的属性.
280 
281 _.uniq([1, 2, 1, 3, 1, 4]);
282 => [1, 2, 3, 4]
283 
284 zip_.zip(*arrays)
285 将 每一个arrays中相应位置的值合并在一块儿。在合并分开保存的数据时颇有用. 若是你用来处理矩阵嵌套数组时, _.zip.apply 能够作相似的效果。
286 
287 _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
288 => [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
289 
290 _.zip.apply(_, arrayOfRowsOfData);
291 => arrayOfColumnsOfData
292 
293 object_.object(list, [values])
294 将数组转换为对象。传递任何一个单独[key, value]对的列表,或者一个键的列表和一个值得列表。 若是存在重复键,最后一个值将被返回。
295 
296 _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
297 => {moe: 30, larry: 40, curly: 50}
298 
299 _.object([['moe', 30], ['larry', 40], ['curly', 50]]);
300 => {moe: 30, larry: 40, curly: 50}
301 
302 indexOf_.indexOf(array, value, [isSorted])
303 返回value在该 array 中的索引值,若是value不存在 array中就返回-1。使用原生的indexOf 函数,除非它失效。若是您正在使用一个大数组,你知道数组已经排序,传递true给isSorted将更快的用二进制搜索..,或者,传递一个数字做为第三个参数,为了在给定的索引的数组中寻找第一个匹配值。
304 
305 _.indexOf([1, 2, 3], 2);
306 => 1
307 
308 lastIndexOf_.lastIndexOf(array, value, [fromIndex])
309 返回value在该 array 中的从最后开始的索引值,若是value不存在 array中就返回-1。若是支持原生的lastIndexOf,将使用原生的lastIndexOf函数。 传递fromIndex将从你给定的索性值开始搜索。
310 
311 _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
312 => 4
313 
314 sortedIndex_.sortedIndex(list, value, [iteratee], [context])
315 使用二分查找肯定value在list中的位置序号,value按此序号插入能保持list原有的排序。 若是提供iterator函数,iterator将做为list排序的依据,包括你传递的value 。 iterator也能够是字符串的属性名用来排序(好比length)。
316 
317 _.sortedIndex([10, 20, 30, 40, 50], 35);
318 => 3
319 
320 var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}];
321 _.sortedIndex(stooges, {name: 'larry', age: 50}, 'age');
322 => 1
323 
324 range_.range([start], stop, [step])
325 一个用来建立整数灵活编号的列表的函数,便于each 和 map循环。若是省略start则默认为 0;step 默认为 1.返回一个从start 到stop的整数的列表,用step来增长 (或减小)独占。值得注意的是,若是stop值在start前面(也就是stop值小于start值),那么值域会被认为是零长度,而不是负增加。-若是你要一个负数的值域 ,请使用负数step.
326 
327 _.range(10);
328 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
329 _.range(1, 11);
330 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
331 _.range(0, 30, 5);
332 => [0, 5, 10, 15, 20, 25]
333 _.range(0, -10, -1);
334 => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
335 _.range(0);
336 => []
337 
338 与函数有关的函数(Function (uh, ahem) Functions)
339 
340 bind_.bind(function, object, *arguments)
341 绑定函数 function 到对象 object 上, 也就是不管什么时候调用函数, 函数里的 this 都指向这个 object. 任意可选参数 arguments 能够传递给函数 function , 能够填充函数所须要的参数, 这也被称为 partial application。对于没有结合上下文的partial application绑定,请使用partial。
342 (注:partial application翻译成“部分应用”或者“偏函数应用”。partial application能够被描述为一个函数,它接受必定数目的参数,绑定值到一个或多个这些参数,并返回一个新的函数,这个返回函数只接受剩余未绑定值的参数。参见:http://en.wikipedia.org/wiki/Partial_application。感谢@一任风月忆秋年的建议)。
343 
344 var func = function(greeting){ return greeting + ': ' + this.name };
345 func = _.bind(func, {name: 'moe'}, 'hi');
346 func();
347 => 'hi: moe'
348 
349 bindAll_.bindAll(object, *methodNames)
350 把methodNames参数指定的一些方法绑定到object上,这些方法就会在对象的上下文环境中执行。绑定函数用做事件处理函数时很是便利,不然函数被调用时this一点用也没有。methodNames参数是必须的。
351 
352 var buttonView = {
353   label  : 'underscore',
354   onClick: function(){ alert('clicked: ' + this.label); },
355   onHover: function(){ console.log('hovering: ' + this.label); }
356 };
357 _.bindAll(buttonView, 'onClick', 'onHover');
358 // When the button is clicked, this.label will have the correct value.
359 jQuery('#underscore_button').bind('click', buttonView.onClick);
360 
361 partial_.partial(function, *arguments)
362 局部应用一个函数填充在任意个数的 参数,不改变其动态this值。和bind方法很相近。你能够在你的参数列表中传递_来指定一个参数 ,不该该被预先填充, but left open to supply at call-time. You may pass _ in your list of arguments to specify an argument that should not be pre-filled, but left open to supply at call-time.(翻译很差,求好的翻译)
363 
364 var add = function(a, b) { return a + b; };
365 add5 = _.partial(add, 5);
366 add5(10);
367 => 15
368 
369 memoize_.memoize(function, [hashFunction])
370 Memoizes方法能够缓存某函数的计算结果。对于耗时较长的计算是颇有帮助的。若是传递了 hashFunction 参数,就用 hashFunction 的返回值做为key存储函数的计算结果。 hashFunction 默认使用function的第一个参数做为key。memoized值的缓存 可做为 返回函数的cache属性。
371 
372 var fibonacci = _.memoize(function(n) {
373   return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
374 });
375 
376 delay_.delay(function, wait, *arguments)
377 相似setTimeout,等待wait毫秒后调用function。若是传递可选的参数arguments,当函数function执行时, arguments 会做为参数传入。
378 
379 var log = _.bind(console.log, console);
380 _.delay(log, 1000, 'logged later');
381 => 'logged later' // Appears after one second.
382 
383 defer_.defer(function, *arguments)
384 延迟调用function直到当前调用栈清空为止,相似使用延时为0的setTimeout方法。对于执行开销大的计算和无阻塞UI线程的HTML渲染时候很是有用。 若是传递arguments参数,当函数function执行时, arguments 会做为参数传入。
385 
386 _.defer(function(){ alert('deferred'); });
387 // Returns from the function before the alert runs.
388 
389 throttle_.throttle(function, wait, [options])
390 建立并返回一个像节流阀同样的函数,当重复调用函数的时候,最多每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。(注:详见:javascript函数的throttle和debounce)
391 
392 默认状况下,throttle将在你调用的第一时间尽快执行这个function,而且,若是你在wait周期内调用任意次数的函数,都将尽快的被覆盖。若是你想禁用第一次首先执行的话,传递{leading: false},还有若是你想禁用最后一次执行的话,传递{trailing: false}。
393 
394 var throttled = _.throttle(updatePosition, 100);
395 $(window).scroll(throttled);
396 
397 debounce_.debounce(function, wait, [immediate])
398 返回 function 函数的防反跳版本, 将延迟函数的执行(真正的执行)在函数最后一次调用时刻的 wait 毫秒以后. 对于必须在一些输入(可能是一些用户操做)中止到达以后执行的行为有帮助。 例如: 渲染一个Markdown格式的评论预览, 当窗口中止改变大小以后从新计算布局, 等等.
399 
400 传参 immediate 为 true, debounce会在 wait 时间间隔的开始调用这个函数 。(注:而且在 waite 的时间以内,不会再次调用。)在相似不当心点了提交按钮两下而提交了两次的状况下颇有用。 (感谢 @ProgramKid 的翻译建议)
401 
402 var lazyLayout = _.debounce(calculateLayout, 300);
403 $(window).resize(lazyLayout);
404 
405 once_.once(function)
406 建立一个只能调用一次的函数。重复调用改进的方法也没有效果,只会返回第一次执行时的结果。 做为初始化函数使用时很是有用, 不用再设一个boolean值来检查是否已经初始化完成.
407 
408 var initialize = _.once(createApplication);
409 initialize();
410 initialize();
411 // Application is only created once.
412 
413 after_.after(count, function)
414 建立一个函数, 只有在运行了 count 次以后才有效果. 在处理同组异步请求返回结果时, 若是你要确保同组里全部异步请求完成以后才 执行这个函数, 这将很是有用。
415 
416 var renderNotes = _.after(notes.length, render);
417 _.each(notes, function(note) {
418   note.asyncSave({success: renderNotes});
419 });
420 // renderNotes is run once, after all notes have saved.
421 
422 before_.before(count, function)
423 建立一个函数,调用不超过count 次。 当count已经达到时,最后一个函数调用的结果 是被记住并返回 。
424 
425 var monthlyMeeting = _.before(3, askForRaise);
426 monthlyMeeting();
427 monthlyMeeting();
428 monthlyMeeting();
429 // the result of any subsequent calls is the same as the second call
430 
431 wrap_.wrap(function, wrapper)
432 将第一个函数 function 封装到函数 wrapper 里面, 并把函数 function 做为第一个参数传给 wrapper. 这样可让 wrapper 在 function 运行以前和以后 执行代码, 调整参数而后附有条件地执行.
433 
434 var hello = function(name) { return "hello: " + name; };
435 hello = _.wrap(hello, function(func) {
436   return "before, " + func("moe") + ", after";
437 });
438 hello();
439 => 'before, hello: moe, after'
440 
441 negate_.negate(predicate)
442 返回一个新的predicate函数的否认版本。
443 
444 var isFalsy = _.negate(Boolean);
445 _.find([-2, -1, 0, 1, 2], isFalsy);
446 => 0
447 
448 compose_.compose(*functions)
449 返回函数集 functions 组合后的复合函数, 也就是一个函数执行完以后把返回的结果再做为参数赋给下一个函数来执行. 以此类推. 在数学里, 把函数 f(), g(), 和 h() 组合起来能够获得复合函数 f(g(h()))。
450 
451 var greet    = function(name){ return "hi: " + name; };
452 var exclaim  = function(statement){ return statement.toUpperCase() + "!"; };
453 var welcome = _.compose(greet, exclaim);
454 welcome('moe');
455 => 'hi: MOE!'
456 
457 对象函数(Object Functions)
458 
459 keys_.keys(object)
460 获取object对象全部的属性名称。
461 
462 _.keys({one: 1, two: 2, three: 3});
463 => ["one", "two", "three"]
464 
465 values_.values(object)
466 返回object对象全部的属性值。
467 
468 _.values({one: 1, two: 2, three: 3});
469 => [1, 2, 3]
470 
471 pairs_.pairs(object)
472 把一个对象转变为一个[key, value]形式的数组。
473 
474 _.pairs({one: 1, two: 2, three: 3});
475 => [["one", 1], ["two", 2], ["three", 3]]
476 
477 invert_.invert(object)
478 返回一个object副本,使其键(keys)和值(values)对换。对于这个操做,必须确保object里全部的值都是惟一的且能够序列号成字符串.
479 
480 _.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"});
481 => {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};
482 
483 functions_.functions(object) 别名: methods
484 返回一个对象里全部的方法名, 并且是已经排序的 — 也就是说, 对象里每一个方法(属性值是一个函数)的名称.
485 
486 _.functions(_);
487 => ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
488 
489 extend_.extend(destination, *sources)
490 复制source对象中的全部属性覆盖到destination对象上,而且返回 destination 对象. 复制是按顺序的, 因此后面的对象属性会把前面的对象属性覆盖掉(若是有重复).
491 
492 _.extend({name: 'moe'}, {age: 50});
493 => {name: 'moe', age: 50}
494 
495 pick_.pick(object, *keys)
496 返回一个object副本,只过滤出keys(有效的键组成的数组)参数指定的属性值。或者接受一个判断函数,指定挑选哪一个key。
497 
498 _.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
499 => {name: 'moe', age: 50}
500 _.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
501   return _.isNumber(value);
502 });
503 => {age: 50}
504 
505 omit_.omit(object, *keys)
506 返回一个object副本,只过滤出除去keys(有效的键组成的数组)参数指定的属性值。 或者接受一个判断函数,指定忽略哪一个key。
507 
508 _.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
509 => {name: 'moe', age: 50}
510 _.omit({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
511   return _.isNumber(value);
512 });
513 => {name: 'moe', userid: 'moe1'}
514 
515 defaults_.defaults(object, *defaults)
516 用defaults对象填充object 中的undefined属性。 而且返回这个object。一旦这个属性被填充,再使用defaults方法将不会有任何效果。(感谢@一任风月忆秋年的拍砖)
517 
518 var iceCream = {flavor: "chocolate"};
519 _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
520 => {flavor: "chocolate", sprinkles: "lots"}
521 
522 clone_.clone(object)
523 建立 一个浅复制(浅拷贝)的克隆object。任何嵌套的对象或数组都经过引用拷贝,不会复制。
524 
525 _.clone({name: 'moe'});
526 => {name: 'moe'};
527 
528 tap_.tap(object, interceptor)
529 用 object做为参数来调用函数interceptor,而后返回object。这种方法的主要意图是做为函数链式调用 的一环, 为了对此对象执行操做并返回对象自己。
530 
531 _.chain([1,2,3,200])
532   .filter(function(num) { return num % 2 == 0; })
533   .tap(alert)
534   .map(function(num) { return num * num })
535   .value();
536 => // [2, 200] (alerted)
537 => [4, 40000]
538 
539 has_.has(object, key)
540 对象是否包含给定的键吗?等同于object.hasOwnProperty(key),可是使用hasOwnProperty 函数的一个安全引用,以防意外覆盖。
541 
542 _.has({a: 1, b: 2, c: 3}, "b");
543 => true
544 
545 property_.property(key)
546 返回一个函数,这个函数返回任何传入的对象的key 属性。
547 
548 var moe = {name: 'moe'};
549 'moe' === _.property('name')(moe);
550 => true
551 
552 matches_.matches(attrs)
553 返回一个断言函数,这个函数会给你一个断言 能够用来辨别 给定的对象是否匹配attrs指定键/值属性。
554 
555 var ready = _.matches({selected: true, visible: true});
556 var readyToGoList = _.filter(list, ready);
557 
558 isEqual_.isEqual(object, other)
559 执行两个对象之间的优化深度比较,肯定他们是否应被视为相等。
560 
561 var moe   = {name: 'moe', luckyNumbers: [13, 27, 34]};
562 var clone = {name: 'moe', luckyNumbers: [13, 27, 34]};
563 moe == clone;
564 => false
565 _.isEqual(moe, clone);
566 => true
567 
568 isEmpty_.isEmpty(object)
569 若是object 不包含任何值(没有可枚举的属性),返回true。 对于字符串和类数组(array-like)对象,若是length属性为0,那么_.isEmpty检查返回true。
570 
571 _.isEmpty([1, 2, 3]);
572 => false
573 _.isEmpty({});
574 => true
575 
576 isElement_.isElement(object)
577 若是object是一个DOM元素,返回true。
578 
579 _.isElement(jQuery('body')[0]);
580 => true
581 
582 isArray_.isArray(object)
583 若是object是一个数组,返回true。
584 
585 (function(){ return _.isArray(arguments); })();
586 => false
587 _.isArray([1,2,3]);
588 => true
589 
590 isObject_.isObject(value)
591 若是object是一个对象,返回true。须要注意的是JavaScript数组和函数是对象,字符串和数字不是。
592 
593 _.isObject({});
594 => true
595 _.isObject(1);
596 => false
597 
598 isArguments_.isArguments(object)
599 若是object是一个参数对象,返回true。
600 
601 (function(){ return _.isArguments(arguments); })(1, 2, 3);
602 => true
603 _.isArguments([1,2,3]);
604 => false
605 
606 isFunction_.isFunction(object)
607 若是object是一个函数(Function),返回true。
608 
609 _.isFunction(alert);
610 => true
611 
612 isString_.isString(object)
613 若是object是一个字符串,返回true。
614 
615 _.isString("moe");
616 => true
617 
618 isNumber_.isNumber(object)
619 若是object是一个数值,返回true (包括 NaN)。
620 
621 _.isNumber(8.4 * 5);
622 => true
623 
624 isFinite_.isFinite(object)
625 若是object是一个有限的数字,返回true。
626 
627 _.isFinite(-101);
628 => true
629 
630 _.isFinite(-Infinity);
631 => false
632 
633 isBoolean_.isBoolean(object)
634 若是object是一个布尔值,返回true。 Returns true if object is either true or false.
635 
636 _.isBoolean(null);
637 => false
638 
639 isDate_.isDate(object)
640 若是object是一个Date类型(日期时间),返回true。
641 
642 _.isDate(new Date());
643 => true
644 
645 isRegExp_.isRegExp(object)
646 若是object是一个正则表达式,返回true。
647 
648 _.isRegExp(/moe/);
649 => true
650 
651 isNaN_.isNaN(object)
652 若是object是 NaN,返回true。
653 注意: 这和原生的isNaN 函数不同,若是变量是undefined,原生的isNaN 函数也会返回 true654 
655 _.isNaN(NaN);
656 => true
657 isNaN(undefined);
658 => true
659 _.isNaN(undefined);
660 => false
661 
662 isNull_.isNull(object)
663 若是object的值是 null,返回true。
664 
665 _.isNull(null);
666 => true
667 _.isNull(undefined);
668 => false
669 
670 isUndefined_.isUndefined(value)
671 若是value是undefined,返回true。
672 
673 _.isUndefined(window.missingVariable);
674 => true
675 
676 实用功能(Utility Functions)
677 
678 noConflict_.noConflict()
679 放弃Underscore 的控制变量"_"。返回Underscore 对象的引用。
680 
681 var underscore = _.noConflict();
682 
683 identity_.identity(value)
684 返回与传入参数相等的值. 至关于数学里的: f(x) = x
685 这个函数看似无用, 可是在Underscore里被用做默认的迭代器iterator.
686 
687 var moe = {name: 'moe'};
688 moe === _.identity(moe);
689 => true
690 
691 constant_.constant(value)
692 建立一个函数,这个函数 返回相同的值 用来做为_.constant的参数。
693 
694 var moe = {name: 'moe'};
695 moe === _.constant(moe)();
696 => true
697 
698 noop_.noop()
699 返回undefined,不论传递给它的是什么参数。 能够用做默承认选的回调参数。
700 
701 obj.initialize = _.noop;
702 
703 times_.times(n, iteratee, [context])
704 调用给定的迭代函数n次,每一次调用iteratee传递index参数。生成一个返回值的数组。
705 注意: 本例使用 链式语法。
706 
707 _(3).times(function(n){ genie.grantWishNumber(n); });
708 
709 random_.random(min, max)
710 返回一个min 和 max之间的随机整数。若是你只传递一个参数,那么将返回0和这个参数之间的整数。
711 
712 _.random(0, 100);
713 => 42
714 
715 mixin_.mixin(object)
716 容许用您本身的实用程序函数扩展Underscore。传递一个 {name: function}定义的哈希添加到Underscore对象,以及面向对象封装。
717 
718 _.mixin({
719   capitalize: function(string) {
720     return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
721   }
722 });
723 _("fabio").capitalize();
724 => "Fabio"
725 
726 iteratee_.iteratee(value, [context], [argCount])
727 一个重要的内部函数用来生成可应用到集合中每一个元素的回调, 返回想要的结果 - 不管是等式,任意回调,属性匹配,或属性访问。
728 经过_.iteratee转换判断的Underscore 方法的完整列表是 map, find, filter, reject, every, some, max, min, sortBy, groupBy, indexBy, countBy, sortedIndex, partition, 和 unique.
729 
730 var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
731 _.map(stooges, _.iteratee('age'));
732 => [25, 21, 23];
733 
734 uniqueId_.uniqueId([prefix])
735 为须要的客户端模型或DOM元素生成一个全局惟一的id。若是prefix参数存在, id 将附加给它。
736 
737 _.uniqueId('contact_');
738 => 'contact_104'
739 
740 escape_.escape(string)
741 转义HTML字符串,替换&, <, >, ", ', 和 /字符。
742 
743 _.escape('Curly, Larry & Moe');
744 => "Curly, Larry &amp; Moe"
745 
746 unescape_.unescape(string)
747 和escape相反。转义HTML字符串,替换&, &lt;, &gt;, &quot;, &#96;, 和 &#x2F;字符。
748 
749 _.unescape('Curly, Larry &amp; Moe');
750 => "Curly, Larry & Moe"
751 
752 result_.result(object, property)
753 若是对象 object 中的属性 property 是函数, 则调用它, 不然, 返回它。
754 
755 var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
756 _.result(object, 'cheese');
757 => "crumpets"
758 _.result(object, 'stuff');
759 => "nonsense"
760 
761 now_.now()
762 一个优化的方式来得到一个当前时间的整数时间戳。 可用于实现定时/动画功能。
763 
764 _.now();
765 => 1392066795351
766 
767 template_.template(templateString, [settings])
768 将 JavaScript 模板编译为能够用于页面呈现的函数, 对于经过JSON数据源生成复杂的HTML并呈现出来的操做很是有用。 模板函数可使用 <%= … %>插入变量, 也能够用<% … %>执行任意的 JavaScript 代码。 若是您但愿插入一个值, 并让其进行HTML转义,请使用<%- … %>。 当你要给模板函数赋值的时候,能够传递一个含有与模板对应属性的data对象 。 若是您要写一个一次性的, 您能够传对象 data 做为第二个参数给模板 template 来直接呈现, 这样页面会当即呈现而不是返回一个模板函数. 参数 settings 是一个哈希表包含任何能够覆盖的设置 _.templateSettings.
769 
770 var compiled = _.template("hello: <%= name %>");
771 compiled({name: 'moe'});
772 => "hello: moe"
773 
774 var template = _.template("<b><%- value %></b>");
775 template({value: '<script>'});
776 => "<b>&lt;script&gt;</b>"
777 
778 您也能够在JavaScript代码中使用 print. 有时候这会比使用 <%= ... %> 更方便.
779 
780 var compiled = _.template("<% print('Hello ' + epithet); %>");
781 compiled({epithet: "stooge"});
782 => "Hello stooge"
783 
784 若是ERB式的分隔符您不喜欢, 您能够改变Underscore的模板设置, 使用别的符号来嵌入代码. 定义一个 interpolate 正则表达式来逐字匹配 嵌入代码的语句, 若是想插入转义后的HTML代码 则须要定义一个 escape 正则表达式来匹配, 还有一个 evaluate 正则表达式来匹配 您想要直接一次性执行程序而不须要任何返回值的语句. 您能够定义或省略这三个的任意一个. 例如, 要执行 Mustache.js 类型的模板:
785 
786 _.templateSettings = {
787   interpolate: /\{\{(.+?)\}\}/g
788 };
789 
790 var template = _.template("Hello {{ name }}!");
791 template({name: "Mustache"});
792 => "Hello Mustache!"
793 
794 默认的, template 经过 with 语句 来取得 data 全部的值. 固然, 您也能够在 variable 设置里指定一个变量名. 这样能显著提高模板的渲染速度.
795 
796 _.template("Using 'with': <%= data.answer %>", {variable: 'data'})({answer: 'no'});
797 => "Using 'with': no"
798 
799 预编译模板对调试不可重现的错误颇有帮助. 这是由于预编译的模板能够提供错误的代码行号和堆栈跟踪, 有些模板在客户端(浏览器)上是不能经过编译的 在编译好的模板函数上, 有 source 属性能够提供简单的预编译功能.
800 
801 <script>
802   JST.project = <%= _.template(jstText).source %>;
803 </script>
804 
805 链式语法(Chaining)
806 
807 您能够在面向对象或者函数的风格下使用Underscore, 这取决于您的我的偏好. 如下两行代码均可以 把一个数组里的全部数字乘以2.
808 
809 _.map([1, 2, 3], function(n){ return n * 2; });
810 _([1, 2, 3]).map(function(n){ return n * 2; });
811 
812 对一个对象使用 chain 方法, 会把这个对象封装并 让之后每次方法的调用结束后都返回这个封装的对象, 当您完成了计算, 可使用 value 函数来取得最终的值. 如下是一个同时使用了 map/flatten/reduce 的链式语法例子, 目的是计算一首歌的歌词里每个单词出现的次数.
813 
814 var lyrics = [
815   {line: 1, words: "I'm a lumberjack and I'm okay"},
816   {line: 2, words: "I sleep all night and I work all day"},
817   {line: 3, words: "He's a lumberjack and he's okay"},
818   {line: 4, words: "He sleeps all night and he works all day"}
819 ];
820 
821 _.chain(lyrics)
822   .map(function(line) { return line.words.split(' '); })
823   .flatten()
824   .reduce(function(counts, word) {
825     counts[word] = (counts[word] || 0) + 1;
826     return counts;
827   }, {})
828   .value();
829 
830 => {lumberjack: 2, all: 4, night: 2 ... }
831 
832 此外, 数组原型方法 也经过代理加入到了链式封装的Underscore对象, 因此您能够 在链式语法中直接使用 reverse 或 push 方法, 而后再接着其余的语句.
833 
834 chain_.chain(obj)
835 返回一个封装的对象. 在封装的对象上调用方法会返回封装的对象自己, 直道 value 方法调用为止.
836 
837 var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
838 var youngest = _.chain(stooges)
839   .sortBy(function(stooge){ return stooge.age; })
840   .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
841   .first()
842   .value();
843 => "moe is 21"
844 
845 value_(obj).value()
846 获取封装对象的最终值.
847 
848 _([1, 2, 3]).value();
849 => [1, 2, 3]
相关文章
相关标签/搜索