1
2
3
4
5
6
7
8
9
10
11
12
13
14 root: this
15
16
17
18 previousUnderscore: root._
19
20
21
22
23
24 wrapper: obj =>
25 this._wrapped: obj
26 this
27
28
29
30 breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
31
32
33
34 _: root._: obj => new wrapper(obj)
35
36
37
38 if typeof(exports) != 'undefined' then exports._: _
39
40
41
42 slice: Array.prototype.slice
43 unshift: Array.prototype.unshift
44 toString: Object.prototype.toString
45 hasOwnProperty: Object.prototype.hasOwnProperty
46 propertyIsEnumerable: Object.prototype.propertyIsEnumerable
47
48
49
50 _.VERSION: '0.5.3'
51
52
53
54
55
56
57 _.each: obj, iterator, context =>
58 index: 0
59 try
60 return obj.forEach(iterator, context) if obj.forEach
61 if _.isArray(obj) or _.isArguments(obj)
62 return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
63 iterator.call(context, val, key, obj) for val, key in obj
64 catch e
65 throw e if e isnt breaker
66 obj
67
68
69
70
71 _.map: obj, iterator, context =>
72 return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
73 results: []
74 _.each(obj) value, index, list =>
75 results.push(iterator.call(context, value, index, list))
76 results
77
78
79
80
81 _.reduce: obj, memo, iterator, context =>
82 return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
83 _.each(obj) value, index, list =>
84 memo: iterator.call(context, memo, value, index, list)
85 memo
86
87
88
89
90 _.reduceRight: obj, memo, iterator, context =>
91 return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
92 _.each(_.clone(_.toArray(obj)).reverse()) value, index =>
93 memo: iterator.call(context, memo, value, index, obj)
94 memo
95
96
97
98 _.detect: obj, iterator, context =>
99 result: null
100 _.each(obj) value, index, list =>
101 if iterator.call(context, value, index, list)
102 result: value
103 _.breakLoop()
104 result
105
106
107
108
109 _.select: obj, iterator, context =>
110 if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
111 results: []
112 _.each(obj) value, index, list =>
113 results.push(value) if iterator.call(context, value, index, list)
114 results
115
116
117
118 _.reject: obj, iterator, context =>
119 results: []
120 _.each(obj) value, index, list =>
121 results.push(value) if not iterator.call(context, value, index, list)
122 results
123
124
125
126
127 _.all: obj, iterator, context =>
128 iterator ||= _.identity
129 return obj.every(iterator, context) if obj and _.isFunction(obj.every)
130 result: true
131 _.each(obj) value, index, list =>
132 _.breakLoop() unless (result: result and iterator.call(context, value, index, list))
133 result
134
135
136
137
138 _.any: obj, iterator, context =>
139 iterator ||= _.identity
140 return obj.some(iterator, context) if obj and _.isFunction(obj.some)
141 result: false
142 _.each(obj) value, index, list =>
143 _.breakLoop() if (result: iterator.call(context, value, index, list))
144 result
145
146
147
148
149 _.include: obj, target =>
150 return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
151 for val in obj
152 return true if val is target
153 false
154
155
156
157 _.invoke: obj, method =>
158 args: _.rest(arguments, 2)
159 (if method then val[method] else val).apply(val, args) for val in obj
160
161
162
163 _.pluck: obj, key =>
164 _.map(obj, (val => val[key]))
165
166
167
168 _.max: obj, iterator, context =>
169 return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
170 result: {computed: -Infinity}
171 _.each(obj) value, index, list =>
172 computed: if iterator then iterator.call(context, value, index, list) else value
173 computed >= result.computed and (result: {value: value, computed: computed})
174 result.value
175
176
177
178 _.min: obj, iterator, context =>
179 return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
180 result: {computed: Infinity}
181 _.each(obj) value, index, list =>
182 computed: if iterator then iterator.call(context, value, index, list) else value
183 computed < result.computed and (result: {value: value, computed: computed})
184 result.value
185
186
187
188 _.sortBy: obj, iterator, context =>
189 _.pluck(((_.map(obj) value, index, list =>
190 {value: value, criteria: iterator.call(context, value, index, list)}
191 ).sort() left, right =>
192 a: left.criteria; b: right.criteria
193 if a < b then -1 else if a > b then 1 else 0
194 ), 'value')
195
196
197
198
199 _.sortedIndex: array, obj, iterator =>
200 iterator ||= _.identity
201 low: 0; high: array.length
202 while low < high
203 mid: (low + high) >> 1
204 if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid
205 low
206
207
208
209 _.toArray: iterable =>
210 return [] if (!iterable)
211 return iterable.toArray() if (iterable.toArray)
212 return iterable if (_.isArray(iterable))
213 return slice.call(iterable) if (_.isArguments(iterable))
214 _.values(iterable)
215
216
217
218 _.size: obj => _.toArray(obj).length
219
220
221
222
223
224
225
226 _.first: array, n, guard =>
227 if n and not guard then slice.call(array, 0, n) else array[0]
228
229
230
231
232
233
234 _.rest: array, index, guard =>
235 slice.call(array, if _.isUndefined(index) or guard then 1 else index)
236
237
238
239 _.last: array => array[array.length - 1]
240
241
242
243 _.compact: array => array[i] for i in [0...array.length] when array[i]
244
245
246
247 _.flatten: array =>
248 _.reduce(array, []) memo, value =>
249 return memo.concat(_.flatten(value)) if _.isArray(value)
250 memo.push(value)
251 memo
252
253
254
255 _.without: array =>
256 values: _.rest(arguments)
257 val for val in _.toArray(array) when not _.include(values, val)
258
259
260
261
262 _.uniq: array, isSorted =>
263 memo: []
264 for el, i in _.toArray(array)
265 memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
266 memo
267
268
269
270
271 _.intersect: array =>
272 rest: _.rest(arguments)
273 _.select(_.uniq(array)) item =>
274 _.all(rest) other =>
275 _.indexOf(other, item) >= 0
276
277
278
279
280 _.zip: =>
281 args: _.toArray(arguments)
282 length: _.max(_.pluck(args, 'length'))
283 results: new Array(length)
284 for i in [0...length]
285 results[i]: _.pluck(args, String(i))
286 results
287
288
289
290
291
292 _.indexOf: array, item =>
293 return array.indexOf(item) if array.indexOf
294 i: 0; l: array.length
295 while l - i
296 if array[i] is item then return i else i++
297 -1
298
299
300
301
302 _.lastIndexOf: array, item =>
303 return array.lastIndexOf(item) if array.lastIndexOf
304 i: array.length
305 while i
306 if array[i] is item then return i else i--
307 -1
308
309
310
311
312
313 _.range: start, stop, step =>
314 a: _.toArray(arguments)
315 solo: a.length <= 1
316 i: start: if solo then 0 else a[0];
317 stop: if solo then a[0] else a[1];
318 step: a[2] or 1
319 len: Math.ceil((stop - start) / step)
320 return [] if len <= 0
321 range: new Array(len)
322 idx: 0
323 while true
324 return range if (if step > 0 then i - stop else stop - i) >= 0
325 range[idx]: i
326 idx++
327 i+= step
328
329
330
331
332
333
334 _.bind: func, obj =>
335 args: _.rest(arguments, 2)
336 => func.apply(obj or root, args.concat(_.toArray(arguments)))
337
338
339
340
341 _.bindAll: obj =>
342 funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
343 _.each(funcs, (f => obj[f]: _.bind(obj[f], obj)))
344 obj
345
346
347
348
349 _.delay: func, wait =>
350 args: _.rest(arguments, 2)
351 setTimeout((=> func.apply(func, args)), wait)
352
353
354
355
356 _.defer: func =>
357 _.delay.apply(_, [func, 1].concat(_.rest(arguments)))
358
359
360
361
362
363 _.wrap: func, wrapper =>
364 => wrapper.apply(wrapper, [func].concat(_.toArray(arguments)))
365
366
367
368
369 _.compose: =>
370 funcs: _.toArray(arguments)
371 =>
372 args: _.toArray(arguments)
373 for i in [(funcs.length - 1)..0]
374 args: [funcs[i].apply(this, args)]
375 args[0]
376
377
378
379
380
381 _.keys: obj =>
382 return _.range(0, obj.length) if _.isArray(obj)
383 key for val, key in obj
384
385
386
387 _.values: obj =>
388 _.map(obj, _.identity)
389
390
391
392 _.functions: obj =>
393 _.select(_.keys(obj), key => _.isFunction(obj[key])).sort()
394
395
396
397 _.extend: destination, source =>
398 for val, key in source
399 destination[key]: val
400 destination
401
402
403
404 _.clone: obj =>
405 return obj.slice(0) if _.isArray(obj)
406 _.extend({}, obj)
407
408
409
410
411 _.tap: obj, interceptor =>
412 interceptor(obj)
413 obj
414
415
416
417 _.isEqual: a, b =>
418
419 return true if a is b
420
421 atype: typeof(a); btype: typeof(b)
422 return false if atype isnt btype
423
424 return true if `a == b`
425
426 return false if (!a and b) or (a and !b)
427
428 return a.isEqual(b) if a.isEqual
429
430 return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
431
432 return true if _.isNaN(a) and _.isNaN(b)
433
434 if _.isRegExp(a) and _.isRegExp(b)
435 return a.source is b.source and
436 a.global is b.global and
437 a.ignoreCase is b.ignoreCase and
438 a.multiline is b.multiline
439
440 return false if atype isnt 'object'
441
442 return false if a.length and (a.length isnt b.length)
443
444 aKeys: _.keys(a); bKeys: _.keys(b)
445
446 return false if aKeys.length isnt bKeys.length
447
448
449 return true
450
451
452
453 _.isEmpty: obj => _.keys(obj).length is 0
454
455
456
457 _.isElement: obj => obj and obj.nodeType is 1
458
459
460
461 _.isArray: obj => !!(obj and obj.concat and obj.unshift)
462
463
464
465 _.isArguments: obj => obj and _.isNumber(obj.length) and !_.isArray(obj) and !propertyIsEnumerable.call(obj, 'length')
466
467
468
469 _.isFunction: obj => !!(obj and obj.constructor and obj.call and obj.apply)
470
471
472
473 _.isString: obj => !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
474
475
476
477 _.isNumber: obj => toString.call(obj) is '[object Number]'
478
479
480
481 _.isDate: obj => !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
482
483
484
485 _.isRegExp: obj => !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
486
487
488
489
490 _.isNaN: obj => _.isNumber(obj) and window.isNaN(obj)
491
492
493
494 _.isNull: obj => obj is null
495
496
497
498 _.isUndefined: obj => typeof obj is 'undefined'
499
500
501
502
503
504
505 _.noConflict: =>
506 root._: previousUnderscore
507 this
508
509
510
511 _.identity: value => value
512
513
514
515 _.breakLoop: => throw breaker
516
517
518
519
520 idCounter: 0
521 _.uniqueId: prefix =>
522 (prefix or '') + idCounter++
523
524
525
526
527 _.template: str, data =>
528 `var fn = new Function('obj',
529 'var p=[],print=function(){p.push.apply(p,arguments);};' +
530 'with(obj){p.push(\'' +
531 str.
532 replace(/[\r\t\n]/g, " ").
533 split("<%").join("\t").
534 replace(/((^|%>)[^\t]*)'/g, "$1\r").
535 replace(/\t=(.*?)%>/g, "',$1,'").
536 split("\t").join("');").
537 split("%>").join("p.push('").
538 split("\r").join("\\'") +
539 "');}return p.join('');")`
540 if data then fn(data) else fn
541
542
543
544
545 _.forEach: _.each
546 _.foldl: _.inject: _.reduce
547 _.foldr: _.reduceRight
548 _.filter: _.select
549 _.every: _.all
550 _.some: _.any
551 _.head: _.first
552 _.tail: _.rest
553 _.methods: _.functions
554
555
556
557
558
559 result: obj, chain =>
560 if chain then _(obj).chain() else obj
561
562
563
564 _.each(_.functions(_)) name =>
565 method: _[name]
566 wrapper.prototype[name]: =>
567 unshift.call(arguments, this._wrapped)
568 result(method.apply(_, arguments), this._chain)
569
570
571
572 _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift']) name =>
573 method: Array.prototype[name]
574 wrapper.prototype[name]: =>
575 method.apply(this._wrapped, arguments)
576 result(this._wrapped, this._chain)
577
578
579
580 _.each(['concat', 'join', 'slice']) name =>
581 method: Array.prototype[name]
582 wrapper.prototype[name]: =>
583 result(method.apply(this._wrapped, arguments), this._chain)
584
585
586
587 wrapper.prototype.chain: =>
588 this._chain: true
589 this
590
591
592
593 wrapper.prototype.value: => this._wrapped