~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/embind/underscore-1.4.2.js

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//     Underscore.js 1.4.2
 
2
//     http://underscorejs.org
 
3
//     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
 
4
//     Underscore may be freely distributed under the MIT license.
 
5
 
 
6
//(function() {
 
7
 
 
8
  // Baseline setup
 
9
  // --------------
 
10
 
 
11
  // Establish the root object, `window` in the browser, or `global` on the server.
 
12
  var root = this;
 
13
 
 
14
  // Save the previous value of the `_` variable.
 
15
  var previousUnderscore = root._;
 
16
 
 
17
  // Establish the object that gets returned to break out of a loop iteration.
 
18
  var breaker = {};
 
19
 
 
20
  // Save bytes in the minified (but not gzipped) version:
 
21
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
 
22
 
 
23
  // Create quick reference variables for speed access to core prototypes.
 
24
  var push             = ArrayProto.push,
 
25
      slice            = ArrayProto.slice,
 
26
      concat           = ArrayProto.concat,
 
27
      unshift          = ArrayProto.unshift,
 
28
      toString         = ObjProto.toString,
 
29
      hasOwnProperty   = ObjProto.hasOwnProperty;
 
30
 
 
31
  // All **ECMAScript 5** native function implementations that we hope to use
 
32
  // are declared here.
 
33
  var
 
34
    nativeForEach      = ArrayProto.forEach,
 
35
    nativeMap          = ArrayProto.map,
 
36
    nativeReduce       = ArrayProto.reduce,
 
37
    nativeReduceRight  = ArrayProto.reduceRight,
 
38
    nativeFilter       = ArrayProto.filter,
 
39
    nativeEvery        = ArrayProto.every,
 
40
    nativeSome         = ArrayProto.some,
 
41
    nativeIndexOf      = ArrayProto.indexOf,
 
42
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
 
43
    nativeIsArray      = Array.isArray,
 
44
    nativeKeys         = Object.keys,
 
45
    nativeBind         = FuncProto.bind;
 
46
 
 
47
  // Create a safe reference to the Underscore object for use below.
 
48
  var _ = function(obj) {
 
49
    if (obj instanceof _) return obj;
 
50
    if (!(this instanceof _)) return new _(obj);
 
51
    this._wrapped = obj;
 
52
  };
 
53
 
 
54
  // Export the Underscore object for **Node.js**, with
 
55
  // backwards-compatibility for the old `require()` API. If we're in
 
56
  // the browser, add `_` as a global object via a string identifier,
 
57
  // for Closure Compiler "advanced" mode.
 
58
  if (typeof exports !== 'undefined') {
 
59
    if (typeof module !== 'undefined' && module.exports) {
 
60
      exports = module.exports = _;
 
61
    }
 
62
    exports._ = _;
 
63
  } else {
 
64
    root['_'] = _;
 
65
  }
 
66
 
 
67
  // Current version.
 
68
  _.VERSION = '1.4.2';
 
69
 
 
70
  // Collection Functions
 
71
  // --------------------
 
72
 
 
73
  // The cornerstone, an `each` implementation, aka `forEach`.
 
74
  // Handles objects with the built-in `forEach`, arrays, and raw objects.
 
75
  // Delegates to **ECMAScript 5**'s native `forEach` if available.
 
76
  var each = _.each = _.forEach = function(obj, iterator, context) {
 
77
    if (obj == null) return;
 
78
    if (nativeForEach && obj.forEach === nativeForEach) {
 
79
      obj.forEach(iterator, context);
 
80
    } else if (obj.length === +obj.length) {
 
81
      for (var i = 0, l = obj.length; i < l; i++) {
 
82
        if (iterator.call(context, obj[i], i, obj) === breaker) return;
 
83
      }
 
84
    } else {
 
85
      for (var key in obj) {
 
86
        if (_.has(obj, key)) {
 
87
          if (iterator.call(context, obj[key], key, obj) === breaker) return;
 
88
        }
 
89
      }
 
90
    }
 
91
  };
 
92
 
 
93
  // Return the results of applying the iterator to each element.
 
94
  // Delegates to **ECMAScript 5**'s native `map` if available.
 
95
  _.map = _.collect = function(obj, iterator, context) {
 
96
    var results = [];
 
97
    if (obj == null) return results;
 
98
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
 
99
    each(obj, function(value, index, list) {
 
100
      results[results.length] = iterator.call(context, value, index, list);
 
101
    });
 
102
    return results;
 
103
  };
 
104
 
 
105
  // **Reduce** builds up a single result from a list of values, aka `inject`,
 
106
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
 
107
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
 
108
    var initial = arguments.length > 2;
 
109
    if (obj == null) obj = [];
 
110
    if (nativeReduce && obj.reduce === nativeReduce) {
 
111
      if (context) iterator = _.bind(iterator, context);
 
112
      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
 
113
    }
 
114
    each(obj, function(value, index, list) {
 
115
      if (!initial) {
 
116
        memo = value;
 
117
        initial = true;
 
118
      } else {
 
119
        memo = iterator.call(context, memo, value, index, list);
 
120
      }
 
121
    });
 
122
    if (!initial) throw new TypeError('Reduce of empty array with no initial value');
 
123
    return memo;
 
124
  };
 
125
 
 
126
  // The right-associative version of reduce, also known as `foldr`.
 
127
  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
 
128
  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
 
129
    var initial = arguments.length > 2;
 
130
    if (obj == null) obj = [];
 
131
    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
 
132
      if (context) iterator = _.bind(iterator, context);
 
133
      return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
 
134
    }
 
135
    var length = obj.length;
 
136
    if (length !== +length) {
 
137
      var keys = _.keys(obj);
 
138
      length = keys.length;
 
139
    }
 
140
    each(obj, function(value, index, list) {
 
141
      index = keys ? keys[--length] : --length;
 
142
      if (!initial) {
 
143
        memo = obj[index];
 
144
        initial = true;
 
145
      } else {
 
146
        memo = iterator.call(context, memo, obj[index], index, list);
 
147
      }
 
148
    });
 
149
    if (!initial) throw new TypeError('Reduce of empty array with no initial value');
 
150
    return memo;
 
151
  };
 
152
 
 
153
  // Return the first value which passes a truth test. Aliased as `detect`.
 
154
  _.find = _.detect = function(obj, iterator, context) {
 
155
    var result;
 
156
    any(obj, function(value, index, list) {
 
157
      if (iterator.call(context, value, index, list)) {
 
158
        result = value;
 
159
        return true;
 
160
      }
 
161
    });
 
162
    return result;
 
163
  };
 
164
 
 
165
  // Return all the elements that pass a truth test.
 
166
  // Delegates to **ECMAScript 5**'s native `filter` if available.
 
167
  // Aliased as `select`.
 
168
  _.filter = _.select = function(obj, iterator, context) {
 
169
    var results = [];
 
170
    if (obj == null) return results;
 
171
    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
 
172
    each(obj, function(value, index, list) {
 
173
      if (iterator.call(context, value, index, list)) results[results.length] = value;
 
174
    });
 
175
    return results;
 
176
  };
 
177
 
 
178
  // Return all the elements for which a truth test fails.
 
179
  _.reject = function(obj, iterator, context) {
 
180
    var results = [];
 
181
    if (obj == null) return results;
 
182
    each(obj, function(value, index, list) {
 
183
      if (!iterator.call(context, value, index, list)) results[results.length] = value;
 
184
    });
 
185
    return results;
 
186
  };
 
187
 
 
188
  // Determine whether all of the elements match a truth test.
 
189
  // Delegates to **ECMAScript 5**'s native `every` if available.
 
190
  // Aliased as `all`.
 
191
  _.every = _.all = function(obj, iterator, context) {
 
192
    iterator || (iterator = _.identity);
 
193
    var result = true;
 
194
    if (obj == null) return result;
 
195
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
 
196
    each(obj, function(value, index, list) {
 
197
      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
 
198
    });
 
199
    return !!result;
 
200
  };
 
201
 
 
202
  // Determine if at least one element in the object matches a truth test.
 
203
  // Delegates to **ECMAScript 5**'s native `some` if available.
 
204
  // Aliased as `any`.
 
205
  var any = _.some = _.any = function(obj, iterator, context) {
 
206
    iterator || (iterator = _.identity);
 
207
    var result = false;
 
208
    if (obj == null) return result;
 
209
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
 
210
    each(obj, function(value, index, list) {
 
211
      if (result || (result = iterator.call(context, value, index, list))) return breaker;
 
212
    });
 
213
    return !!result;
 
214
  };
 
215
 
 
216
  // Determine if the array or object contains a given value (using `===`).
 
217
  // Aliased as `include`.
 
218
  _.contains = _.include = function(obj, target) {
 
219
    var found = false;
 
220
    if (obj == null) return found;
 
221
    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
 
222
    found = any(obj, function(value) {
 
223
      return value === target;
 
224
    });
 
225
    return found;
 
226
  };
 
227
 
 
228
  // Invoke a method (with arguments) on every item in a collection.
 
229
  _.invoke = function(obj, method) {
 
230
    var args = slice.call(arguments, 2);
 
231
    return _.map(obj, function(value) {
 
232
      return (_.isFunction(method) ? method : value[method]).apply(value, args);
 
233
    });
 
234
  };
 
235
 
 
236
  // Convenience version of a common use case of `map`: fetching a property.
 
237
  _.pluck = function(obj, key) {
 
238
    return _.map(obj, function(value){ return value[key]; });
 
239
  };
 
240
 
 
241
  // Convenience version of a common use case of `filter`: selecting only objects
 
242
  // with specific `key:value` pairs.
 
243
  _.where = function(obj, attrs) {
 
244
    if (_.isEmpty(attrs)) return [];
 
245
    return _.filter(obj, function(value) {
 
246
      for (var key in attrs) {
 
247
        if (attrs[key] !== value[key]) return false;
 
248
      }
 
249
      return true;
 
250
    });
 
251
  };
 
252
 
 
253
  // Return the maximum element or (element-based computation).
 
254
  // Can't optimize arrays of integers longer than 65,535 elements.
 
255
  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
 
256
  _.max = function(obj, iterator, context) {
 
257
    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
 
258
      return Math.max.apply(Math, obj);
 
259
    }
 
260
    if (!iterator && _.isEmpty(obj)) return -Infinity;
 
261
    var result = {computed : -Infinity};
 
262
    each(obj, function(value, index, list) {
 
263
      var computed = iterator ? iterator.call(context, value, index, list) : value;
 
264
      computed >= result.computed && (result = {value : value, computed : computed});
 
265
    });
 
266
    return result.value;
 
267
  };
 
268
 
 
269
  // Return the minimum element (or element-based computation).
 
270
  _.min = function(obj, iterator, context) {
 
271
    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
 
272
      return Math.min.apply(Math, obj);
 
273
    }
 
274
    if (!iterator && _.isEmpty(obj)) return Infinity;
 
275
    var result = {computed : Infinity};
 
276
    each(obj, function(value, index, list) {
 
277
      var computed = iterator ? iterator.call(context, value, index, list) : value;
 
278
      computed < result.computed && (result = {value : value, computed : computed});
 
279
    });
 
280
    return result.value;
 
281
  };
 
282
 
 
283
  // Shuffle an array.
 
284
  _.shuffle = function(obj) {
 
285
    var rand;
 
286
    var index = 0;
 
287
    var shuffled = [];
 
288
    each(obj, function(value) {
 
289
      rand = _.random(index++);
 
290
      shuffled[index - 1] = shuffled[rand];
 
291
      shuffled[rand] = value;
 
292
    });
 
293
    return shuffled;
 
294
  };
 
295
 
 
296
  // An internal function to generate lookup iterators.
 
297
  var lookupIterator = function(value) {
 
298
    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
 
299
  };
 
300
 
 
301
  // Sort the object's values by a criterion produced by an iterator.
 
302
  _.sortBy = function(obj, value, context) {
 
303
    var iterator = lookupIterator(value);
 
304
    return _.pluck(_.map(obj, function(value, index, list) {
 
305
      return {
 
306
        value : value,
 
307
        index : index,
 
308
        criteria : iterator.call(context, value, index, list)
 
309
      };
 
310
    }).sort(function(left, right) {
 
311
      var a = left.criteria;
 
312
      var b = right.criteria;
 
313
      if (a !== b) {
 
314
        if (a > b || a === void 0) return 1;
 
315
        if (a < b || b === void 0) return -1;
 
316
      }
 
317
      return left.index < right.index ? -1 : 1;
 
318
    }), 'value');
 
319
  };
 
320
 
 
321
  // An internal function used for aggregate "group by" operations.
 
322
  var group = function(obj, value, context, behavior) {
 
323
    var result = {};
 
324
    var iterator = lookupIterator(value);
 
325
    each(obj, function(value, index) {
 
326
      var key = iterator.call(context, value, index, obj);
 
327
      behavior(result, key, value);
 
328
    });
 
329
    return result;
 
330
  };
 
331
 
 
332
  // Groups the object's values by a criterion. Pass either a string attribute
 
333
  // to group by, or a function that returns the criterion.
 
334
  _.groupBy = function(obj, value, context) {
 
335
    return group(obj, value, context, function(result, key, value) {
 
336
      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
 
337
    });
 
338
  };
 
339
 
 
340
  // Counts instances of an object that group by a certain criterion. Pass
 
341
  // either a string attribute to count by, or a function that returns the
 
342
  // criterion.
 
343
  _.countBy = function(obj, value, context) {
 
344
    return group(obj, value, context, function(result, key, value) {
 
345
      if (!_.has(result, key)) result[key] = 0;
 
346
      result[key]++;
 
347
    });
 
348
  };
 
349
 
 
350
  // Use a comparator function to figure out the smallest index at which
 
351
  // an object should be inserted so as to maintain order. Uses binary search.
 
352
  _.sortedIndex = function(array, obj, iterator, context) {
 
353
    iterator = iterator == null ? _.identity : lookupIterator(iterator);
 
354
    var value = iterator.call(context, obj);
 
355
    var low = 0, high = array.length;
 
356
    while (low < high) {
 
357
      var mid = (low + high) >>> 1;
 
358
      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
 
359
    }
 
360
    return low;
 
361
  };
 
362
 
 
363
  // Safely convert anything iterable into a real, live array.
 
364
  _.toArray = function(obj) {
 
365
    if (!obj) return [];
 
366
    if (obj.length === +obj.length) return slice.call(obj);
 
367
    return _.values(obj);
 
368
  };
 
369
 
 
370
  // Return the number of elements in an object.
 
371
  _.size = function(obj) {
 
372
    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
 
373
  };
 
374
 
 
375
  // Array Functions
 
376
  // ---------------
 
377
 
 
378
  // Get the first element of an array. Passing **n** will return the first N
 
379
  // values in the array. Aliased as `head` and `take`. The **guard** check
 
380
  // allows it to work with `_.map`.
 
381
  _.first = _.head = _.take = function(array, n, guard) {
 
382
    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
 
383
  };
 
384
 
 
385
  // Returns everything but the last entry of the array. Especially useful on
 
386
  // the arguments object. Passing **n** will return all the values in
 
387
  // the array, excluding the last N. The **guard** check allows it to work with
 
388
  // `_.map`.
 
389
  _.initial = function(array, n, guard) {
 
390
    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
 
391
  };
 
392
 
 
393
  // Get the last element of an array. Passing **n** will return the last N
 
394
  // values in the array. The **guard** check allows it to work with `_.map`.
 
395
  _.last = function(array, n, guard) {
 
396
    if ((n != null) && !guard) {
 
397
      return slice.call(array, Math.max(array.length - n, 0));
 
398
    } else {
 
399
      return array[array.length - 1];
 
400
    }
 
401
  };
 
402
 
 
403
  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
 
404
  // Especially useful on the arguments object. Passing an **n** will return
 
405
  // the rest N values in the array. The **guard**
 
406
  // check allows it to work with `_.map`.
 
407
  _.rest = _.tail = _.drop = function(array, n, guard) {
 
408
    return slice.call(array, (n == null) || guard ? 1 : n);
 
409
  };
 
410
 
 
411
  // Trim out all falsy values from an array.
 
412
  _.compact = function(array) {
 
413
    return _.filter(array, function(value){ return !!value; });
 
414
  };
 
415
 
 
416
  // Internal implementation of a recursive `flatten` function.
 
417
  var flatten = function(input, shallow, output) {
 
418
    each(input, function(value) {
 
419
      if (_.isArray(value)) {
 
420
        shallow ? push.apply(output, value) : flatten(value, shallow, output);
 
421
      } else {
 
422
        output.push(value);
 
423
      }
 
424
    });
 
425
    return output;
 
426
  };
 
427
 
 
428
  // Return a completely flattened version of an array.
 
429
  _.flatten = function(array, shallow) {
 
430
    return flatten(array, shallow, []);
 
431
  };
 
432
 
 
433
  // Return a version of the array that does not contain the specified value(s).
 
434
  _.without = function(array) {
 
435
    return _.difference(array, slice.call(arguments, 1));
 
436
  };
 
437
 
 
438
  // Produce a duplicate-free version of the array. If the array has already
 
439
  // been sorted, you have the option of using a faster algorithm.
 
440
  // Aliased as `unique`.
 
441
  _.uniq = _.unique = function(array, isSorted, iterator, context) {
 
442
    var initial = iterator ? _.map(array, iterator, context) : array;
 
443
    var results = [];
 
444
    var seen = [];
 
445
    each(initial, function(value, index) {
 
446
      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
 
447
        seen.push(value);
 
448
        results.push(array[index]);
 
449
      }
 
450
    });
 
451
    return results;
 
452
  };
 
453
 
 
454
  // Produce an array that contains the union: each distinct element from all of
 
455
  // the passed-in arrays.
 
456
  _.union = function() {
 
457
    return _.uniq(concat.apply(ArrayProto, arguments));
 
458
  };
 
459
 
 
460
  // Produce an array that contains every item shared between all the
 
461
  // passed-in arrays.
 
462
  _.intersection = function(array) {
 
463
    var rest = slice.call(arguments, 1);
 
464
    return _.filter(_.uniq(array), function(item) {
 
465
      return _.every(rest, function(other) {
 
466
        return _.indexOf(other, item) >= 0;
 
467
      });
 
468
    });
 
469
  };
 
470
 
 
471
  // Take the difference between one array and a number of other arrays.
 
472
  // Only the elements present in just the first array will remain.
 
473
  _.difference = function(array) {
 
474
    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
 
475
    return _.filter(array, function(value){ return !_.contains(rest, value); });
 
476
  };
 
477
 
 
478
  // Zip together multiple lists into a single array -- elements that share
 
479
  // an index go together.
 
480
  _.zip = function() {
 
481
    var args = slice.call(arguments);
 
482
    var length = _.max(_.pluck(args, 'length'));
 
483
    var results = new Array(length);
 
484
    for (var i = 0; i < length; i++) {
 
485
      results[i] = _.pluck(args, "" + i);
 
486
    }
 
487
    return results;
 
488
  };
 
489
 
 
490
  // Converts lists into objects. Pass either a single array of `[key, value]`
 
491
  // pairs, or two parallel arrays of the same length -- one of keys, and one of
 
492
  // the corresponding values.
 
493
  _.object = function(list, values) {
 
494
    var result = {};
 
495
    for (var i = 0, l = list.length; i < l; i++) {
 
496
      if (values) {
 
497
        result[list[i]] = values[i];
 
498
      } else {
 
499
        result[list[i][0]] = list[i][1];
 
500
      }
 
501
    }
 
502
    return result;
 
503
  };
 
504
 
 
505
  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
 
506
  // we need this function. Return the position of the first occurrence of an
 
507
  // item in an array, or -1 if the item is not included in the array.
 
508
  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
 
509
  // If the array is large and already in sort order, pass `true`
 
510
  // for **isSorted** to use binary search.
 
511
  _.indexOf = function(array, item, isSorted) {
 
512
    if (array == null) return -1;
 
513
    var i = 0, l = array.length;
 
514
    if (isSorted) {
 
515
      if (typeof isSorted == 'number') {
 
516
        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
 
517
      } else {
 
518
        i = _.sortedIndex(array, item);
 
519
        return array[i] === item ? i : -1;
 
520
      }
 
521
    }
 
522
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
 
523
    for (; i < l; i++) if (array[i] === item) return i;
 
524
    return -1;
 
525
  };
 
526
 
 
527
  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
 
528
  _.lastIndexOf = function(array, item, from) {
 
529
    if (array == null) return -1;
 
530
    var hasIndex = from != null;
 
531
    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
 
532
      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
 
533
    }
 
534
    var i = (hasIndex ? from : array.length);
 
535
    while (i--) if (array[i] === item) return i;
 
536
    return -1;
 
537
  };
 
538
 
 
539
  // Generate an integer Array containing an arithmetic progression. A port of
 
540
  // the native Python `range()` function. See
 
541
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
 
542
  _.range = function(start, stop, step) {
 
543
    if (arguments.length <= 1) {
 
544
      stop = start || 0;
 
545
      start = 0;
 
546
    }
 
547
    step = arguments[2] || 1;
 
548
 
 
549
    var len = Math.max(Math.ceil((stop - start) / step), 0);
 
550
    var idx = 0;
 
551
    var range = new Array(len);
 
552
 
 
553
    while(idx < len) {
 
554
      range[idx++] = start;
 
555
      start += step;
 
556
    }
 
557
 
 
558
    return range;
 
559
  };
 
560
 
 
561
  // Function (ahem) Functions
 
562
  // ------------------
 
563
 
 
564
  // Reusable constructor function for prototype setting.
 
565
  var ctor = function(){};
 
566
 
 
567
  // Create a function bound to a given object (assigning `this`, and arguments,
 
568
  // optionally). Binding with arguments is also known as `curry`.
 
569
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
 
570
  // We check for `func.bind` first, to fail fast when `func` is undefined.
 
571
  _.bind = function bind(func, context) {
 
572
    var bound, args;
 
573
    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
 
574
    if (!_.isFunction(func)) throw new TypeError;
 
575
    args = slice.call(arguments, 2);
 
576
    return bound = function() {
 
577
      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
 
578
      ctor.prototype = func.prototype;
 
579
      var self = new ctor;
 
580
      var result = func.apply(self, args.concat(slice.call(arguments)));
 
581
      if (Object(result) === result) return result;
 
582
      return self;
 
583
    };
 
584
  };
 
585
 
 
586
  // Bind all of an object's methods to that object. Useful for ensuring that
 
587
  // all callbacks defined on an object belong to it.
 
588
  _.bindAll = function(obj) {
 
589
    var funcs = slice.call(arguments, 1);
 
590
    if (funcs.length == 0) funcs = _.functions(obj);
 
591
    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
 
592
    return obj;
 
593
  };
 
594
 
 
595
  // Memoize an expensive function by storing its results.
 
596
  _.memoize = function(func, hasher) {
 
597
    var memo = {};
 
598
    hasher || (hasher = _.identity);
 
599
    return function() {
 
600
      var key = hasher.apply(this, arguments);
 
601
      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
 
602
    };
 
603
  };
 
604
 
 
605
  // Delays a function for the given number of milliseconds, and then calls
 
606
  // it with the arguments supplied.
 
607
  _.delay = function(func, wait) {
 
608
    var args = slice.call(arguments, 2);
 
609
    return setTimeout(function(){ return func.apply(null, args); }, wait);
 
610
  };
 
611
 
 
612
  // Defers a function, scheduling it to run after the current call stack has
 
613
  // cleared.
 
614
  _.defer = function(func) {
 
615
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
 
616
  };
 
617
 
 
618
  // Returns a function, that, when invoked, will only be triggered at most once
 
619
  // during a given window of time.
 
620
  _.throttle = function(func, wait) {
 
621
    var context, args, timeout, throttling, more, result;
 
622
    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
 
623
    return function() {
 
624
      context = this; args = arguments;
 
625
      var later = function() {
 
626
        timeout = null;
 
627
        if (more) {
 
628
          result = func.apply(context, args);
 
629
        }
 
630
        whenDone();
 
631
      };
 
632
      if (!timeout) timeout = setTimeout(later, wait);
 
633
      if (throttling) {
 
634
        more = true;
 
635
      } else {
 
636
        throttling = true;
 
637
        result = func.apply(context, args);
 
638
      }
 
639
      whenDone();
 
640
      return result;
 
641
    };
 
642
  };
 
643
 
 
644
  // Returns a function, that, as long as it continues to be invoked, will not
 
645
  // be triggered. The function will be called after it stops being called for
 
646
  // N milliseconds. If `immediate` is passed, trigger the function on the
 
647
  // leading edge, instead of the trailing.
 
648
  _.debounce = function(func, wait, immediate) {
 
649
    var timeout, result;
 
650
    return function() {
 
651
      var context = this, args = arguments;
 
652
      var later = function() {
 
653
        timeout = null;
 
654
        if (!immediate) result = func.apply(context, args);
 
655
      };
 
656
      var callNow = immediate && !timeout;
 
657
      clearTimeout(timeout);
 
658
      timeout = setTimeout(later, wait);
 
659
      if (callNow) result = func.apply(context, args);
 
660
      return result;
 
661
    };
 
662
  };
 
663
 
 
664
  // Returns a function that will be executed at most one time, no matter how
 
665
  // often you call it. Useful for lazy initialization.
 
666
  _.once = function(func) {
 
667
    var ran = false, memo;
 
668
    return function() {
 
669
      if (ran) return memo;
 
670
      ran = true;
 
671
      memo = func.apply(this, arguments);
 
672
      func = null;
 
673
      return memo;
 
674
    };
 
675
  };
 
676
 
 
677
  // Returns the first function passed as an argument to the second,
 
678
  // allowing you to adjust arguments, run code before and after, and
 
679
  // conditionally execute the original function.
 
680
  _.wrap = function(func, wrapper) {
 
681
    return function() {
 
682
      var args = [func];
 
683
      push.apply(args, arguments);
 
684
      return wrapper.apply(this, args);
 
685
    };
 
686
  };
 
687
 
 
688
  // Returns a function that is the composition of a list of functions, each
 
689
  // consuming the return value of the function that follows.
 
690
  _.compose = function() {
 
691
    var funcs = arguments;
 
692
    return function() {
 
693
      var args = arguments;
 
694
      for (var i = funcs.length - 1; i >= 0; i--) {
 
695
        args = [funcs[i].apply(this, args)];
 
696
      }
 
697
      return args[0];
 
698
    };
 
699
  };
 
700
 
 
701
  // Returns a function that will only be executed after being called N times.
 
702
  _.after = function(times, func) {
 
703
    if (times <= 0) return func();
 
704
    return function() {
 
705
      if (--times < 1) {
 
706
        return func.apply(this, arguments);
 
707
      }
 
708
    };
 
709
  };
 
710
 
 
711
  // Object Functions
 
712
  // ----------------
 
713
 
 
714
  // Retrieve the names of an object's properties.
 
715
  // Delegates to **ECMAScript 5**'s native `Object.keys`
 
716
  _.keys = nativeKeys || function(obj) {
 
717
    if (obj !== Object(obj)) throw new TypeError('Invalid object');
 
718
    var keys = [];
 
719
    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
 
720
    return keys;
 
721
  };
 
722
 
 
723
  // Retrieve the values of an object's properties.
 
724
  _.values = function(obj) {
 
725
    var values = [];
 
726
    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
 
727
    return values;
 
728
  };
 
729
 
 
730
  // Convert an object into a list of `[key, value]` pairs.
 
731
  _.pairs = function(obj) {
 
732
    var pairs = [];
 
733
    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
 
734
    return pairs;
 
735
  };
 
736
 
 
737
  // Invert the keys and values of an object. The values must be serializable.
 
738
  _.invert = function(obj) {
 
739
    var result = {};
 
740
    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
 
741
    return result;
 
742
  };
 
743
 
 
744
  // Return a sorted list of the function names available on the object.
 
745
  // Aliased as `methods`
 
746
  _.functions = _.methods = function(obj) {
 
747
    var names = [];
 
748
    for (var key in obj) {
 
749
      if (_.isFunction(obj[key])) names.push(key);
 
750
    }
 
751
    return names.sort();
 
752
  };
 
753
 
 
754
  // Extend a given object with all the properties in passed-in object(s).
 
755
  _.extend = function(obj) {
 
756
    each(slice.call(arguments, 1), function(source) {
 
757
      for (var prop in source) {
 
758
        obj[prop] = source[prop];
 
759
      }
 
760
    });
 
761
    return obj;
 
762
  };
 
763
 
 
764
  // Return a copy of the object only containing the whitelisted properties.
 
765
  _.pick = function(obj) {
 
766
    var copy = {};
 
767
    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
 
768
    each(keys, function(key) {
 
769
      if (key in obj) copy[key] = obj[key];
 
770
    });
 
771
    return copy;
 
772
  };
 
773
 
 
774
   // Return a copy of the object without the blacklisted properties.
 
775
  _.omit = function(obj) {
 
776
    var copy = {};
 
777
    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
 
778
    for (var key in obj) {
 
779
      if (!_.contains(keys, key)) copy[key] = obj[key];
 
780
    }
 
781
    return copy;
 
782
  };
 
783
 
 
784
  // Fill in a given object with default properties.
 
785
  _.defaults = function(obj) {
 
786
    each(slice.call(arguments, 1), function(source) {
 
787
      for (var prop in source) {
 
788
        if (obj[prop] == null) obj[prop] = source[prop];
 
789
      }
 
790
    });
 
791
    return obj;
 
792
  };
 
793
 
 
794
  // Create a (shallow-cloned) duplicate of an object.
 
795
  _.clone = function(obj) {
 
796
    if (!_.isObject(obj)) return obj;
 
797
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
 
798
  };
 
799
 
 
800
  // Invokes interceptor with the obj, and then returns obj.
 
801
  // The primary purpose of this method is to "tap into" a method chain, in
 
802
  // order to perform operations on intermediate results within the chain.
 
803
  _.tap = function(obj, interceptor) {
 
804
    interceptor(obj);
 
805
    return obj;
 
806
  };
 
807
 
 
808
  // Internal recursive comparison function for `isEqual`.
 
809
  var eq = function(a, b, aStack, bStack) {
 
810
    // Identical objects are equal. `0 === -0`, but they aren't identical.
 
811
    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
 
812
    if (a === b) return a !== 0 || 1 / a == 1 / b;
 
813
    // A strict comparison is necessary because `null == undefined`.
 
814
    if (a == null || b == null) return a === b;
 
815
    // Unwrap any wrapped objects.
 
816
    if (a instanceof _) a = a._wrapped;
 
817
    if (b instanceof _) b = b._wrapped;
 
818
    // Compare `[[Class]]` names.
 
819
    var className = toString.call(a);
 
820
    if (className != toString.call(b)) return false;
 
821
    switch (className) {
 
822
      // Strings, numbers, dates, and booleans are compared by value.
 
823
      case '[object String]':
 
824
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
 
825
        // equivalent to `new String("5")`.
 
826
        return a == String(b);
 
827
      case '[object Number]':
 
828
        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
 
829
        // other numeric values.
 
830
        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
 
831
      case '[object Date]':
 
832
      case '[object Boolean]':
 
833
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
 
834
        // millisecond representations. Note that invalid dates with millisecond representations
 
835
        // of `NaN` are not equivalent.
 
836
        return +a == +b;
 
837
      // RegExps are compared by their source patterns and flags.
 
838
      case '[object RegExp]':
 
839
        return a.source == b.source &&
 
840
               a.global == b.global &&
 
841
               a.multiline == b.multiline &&
 
842
               a.ignoreCase == b.ignoreCase;
 
843
    }
 
844
    if (typeof a != 'object' || typeof b != 'object') return false;
 
845
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
 
846
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
 
847
    var length = aStack.length;
 
848
    while (length--) {
 
849
      // Linear search. Performance is inversely proportional to the number of
 
850
      // unique nested structures.
 
851
      if (aStack[length] == a) return bStack[length] == b;
 
852
    }
 
853
    // Add the first object to the stack of traversed objects.
 
854
    aStack.push(a);
 
855
    bStack.push(b);
 
856
    var size = 0, result = true;
 
857
    // Recursively compare objects and arrays.
 
858
    if (className == '[object Array]') {
 
859
      // Compare array lengths to determine if a deep comparison is necessary.
 
860
      size = a.length;
 
861
      result = size == b.length;
 
862
      if (result) {
 
863
        // Deep compare the contents, ignoring non-numeric properties.
 
864
        while (size--) {
 
865
          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
 
866
        }
 
867
      }
 
868
    } else {
 
869
      // Objects with different constructors are not equivalent, but `Object`s
 
870
      // from different frames are.
 
871
      var aCtor = a.constructor, bCtor = b.constructor;
 
872
      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
 
873
                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
 
874
        return false;
 
875
      }
 
876
      // Deep compare objects.
 
877
      for (var key in a) {
 
878
        if (_.has(a, key)) {
 
879
          // Count the expected number of properties.
 
880
          size++;
 
881
          // Deep compare each member.
 
882
          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
 
883
        }
 
884
      }
 
885
      // Ensure that both objects contain the same number of properties.
 
886
      if (result) {
 
887
        for (key in b) {
 
888
          if (_.has(b, key) && !(size--)) break;
 
889
        }
 
890
        result = !size;
 
891
      }
 
892
    }
 
893
    // Remove the first object from the stack of traversed objects.
 
894
    aStack.pop();
 
895
    bStack.pop();
 
896
    return result;
 
897
  };
 
898
 
 
899
  // Perform a deep comparison to check if two objects are equal.
 
900
  _.isEqual = function(a, b) {
 
901
    return eq(a, b, [], []);
 
902
  };
 
903
 
 
904
  // Is a given array, string, or object empty?
 
905
  // An "empty" object has no enumerable own-properties.
 
906
  _.isEmpty = function(obj) {
 
907
    if (obj == null) return true;
 
908
    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
 
909
    for (var key in obj) if (_.has(obj, key)) return false;
 
910
    return true;
 
911
  };
 
912
 
 
913
  // Is a given value a DOM element?
 
914
  _.isElement = function(obj) {
 
915
    return !!(obj && obj.nodeType === 1);
 
916
  };
 
917
 
 
918
  // Is a given value an array?
 
919
  // Delegates to ECMA5's native Array.isArray
 
920
  _.isArray = nativeIsArray || function(obj) {
 
921
    return toString.call(obj) == '[object Array]';
 
922
  };
 
923
 
 
924
  // Is a given variable an object?
 
925
  _.isObject = function(obj) {
 
926
    return obj === Object(obj);
 
927
  };
 
928
 
 
929
  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
 
930
  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
 
931
    _['is' + name] = function(obj) {
 
932
      return toString.call(obj) == '[object ' + name + ']';
 
933
    };
 
934
  });
 
935
 
 
936
  // Define a fallback version of the method in browsers (ahem, IE), where
 
937
  // there isn't any inspectable "Arguments" type.
 
938
  if (!_.isArguments(arguments)) {
 
939
    _.isArguments = function(obj) {
 
940
      return !!(obj && _.has(obj, 'callee'));
 
941
    };
 
942
  }
 
943
 
 
944
  // Optimize `isFunction` if appropriate.
 
945
  if (typeof (/./) !== 'function') {
 
946
    _.isFunction = function(obj) {
 
947
      return typeof obj === 'function';
 
948
    };
 
949
  }
 
950
 
 
951
  // Is a given object a finite number?
 
952
  _.isFinite = function(obj) {
 
953
    return _.isNumber(obj) && isFinite(obj);
 
954
  };
 
955
 
 
956
  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
 
957
  _.isNaN = function(obj) {
 
958
    return _.isNumber(obj) && obj != +obj;
 
959
  };
 
960
 
 
961
  // Is a given value a boolean?
 
962
  _.isBoolean = function(obj) {
 
963
    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
 
964
  };
 
965
 
 
966
  // Is a given value equal to null?
 
967
  _.isNull = function(obj) {
 
968
    return obj === null;
 
969
  };
 
970
 
 
971
  // Is a given variable undefined?
 
972
  _.isUndefined = function(obj) {
 
973
    return obj === void 0;
 
974
  };
 
975
 
 
976
  // Shortcut function for checking if an object has a given property directly
 
977
  // on itself (in other words, not on a prototype).
 
978
  _.has = function(obj, key) {
 
979
    return hasOwnProperty.call(obj, key);
 
980
  };
 
981
 
 
982
  // Utility Functions
 
983
  // -----------------
 
984
 
 
985
  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
 
986
  // previous owner. Returns a reference to the Underscore object.
 
987
  _.noConflict = function() {
 
988
    root._ = previousUnderscore;
 
989
    return this;
 
990
  };
 
991
 
 
992
  // Keep the identity function around for default iterators.
 
993
  _.identity = function(value) {
 
994
    return value;
 
995
  };
 
996
 
 
997
  // Run a function **n** times.
 
998
  _.times = function(n, iterator, context) {
 
999
    for (var i = 0; i < n; i++) iterator.call(context, i);
 
1000
  };
 
1001
 
 
1002
  // Return a random integer between min and max (inclusive).
 
1003
  _.random = function(min, max) {
 
1004
    if (max == null) {
 
1005
      max = min;
 
1006
      min = 0;
 
1007
    }
 
1008
    return min + (0 | Math.random() * (max - min + 1));
 
1009
  };
 
1010
 
 
1011
  // List of HTML entities for escaping.
 
1012
  var entityMap = {
 
1013
    escape: {
 
1014
      '&': '&amp;',
 
1015
      '<': '&lt;',
 
1016
      '>': '&gt;',
 
1017
      '"': '&quot;',
 
1018
      "'": '&#x27;',
 
1019
      '/': '&#x2F;'
 
1020
    }
 
1021
  };
 
1022
  entityMap.unescape = _.invert(entityMap.escape);
 
1023
 
 
1024
  // Regexes containing the keys and values listed immediately above.
 
1025
  var entityRegexes = {
 
1026
    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
 
1027
    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
 
1028
  };
 
1029
 
 
1030
  // Functions for escaping and unescaping strings to/from HTML interpolation.
 
1031
  _.each(['escape', 'unescape'], function(method) {
 
1032
    _[method] = function(string) {
 
1033
      if (string == null) return '';
 
1034
      return ('' + string).replace(entityRegexes[method], function(match) {
 
1035
        return entityMap[method][match];
 
1036
      });
 
1037
    };
 
1038
  });
 
1039
 
 
1040
  // If the value of the named property is a function then invoke it;
 
1041
  // otherwise, return it.
 
1042
  _.result = function(object, property) {
 
1043
    if (object == null) return null;
 
1044
    var value = object[property];
 
1045
    return _.isFunction(value) ? value.call(object) : value;
 
1046
  };
 
1047
 
 
1048
  // Add your own custom functions to the Underscore object.
 
1049
  _.mixin = function(obj) {
 
1050
    each(_.functions(obj), function(name){
 
1051
      var func = _[name] = obj[name];
 
1052
      _.prototype[name] = function() {
 
1053
        var args = [this._wrapped];
 
1054
        push.apply(args, arguments);
 
1055
        return result.call(this, func.apply(_, args));
 
1056
      };
 
1057
    });
 
1058
  };
 
1059
 
 
1060
  // Generate a unique integer id (unique within the entire client session).
 
1061
  // Useful for temporary DOM ids.
 
1062
  var idCounter = 0;
 
1063
  _.uniqueId = function(prefix) {
 
1064
    var id = idCounter++;
 
1065
    return prefix ? prefix + id : id;
 
1066
  };
 
1067
 
 
1068
  // By default, Underscore uses ERB-style template delimiters, change the
 
1069
  // following template settings to use alternative delimiters.
 
1070
  _.templateSettings = {
 
1071
    evaluate    : /<%([\s\S]+?)%>/g,
 
1072
    interpolate : /<%=([\s\S]+?)%>/g,
 
1073
    escape      : /<%-([\s\S]+?)%>/g
 
1074
  };
 
1075
 
 
1076
  // When customizing `templateSettings`, if you don't want to define an
 
1077
  // interpolation, evaluation or escaping regex, we need one that is
 
1078
  // guaranteed not to match.
 
1079
  var noMatch = /(.)^/;
 
1080
 
 
1081
  // Certain characters need to be escaped so that they can be put into a
 
1082
  // string literal.
 
1083
  var escapes = {
 
1084
    "'":      "'",
 
1085
    '\\':     '\\',
 
1086
    '\r':     'r',
 
1087
    '\n':     'n',
 
1088
    '\t':     't',
 
1089
    '\u2028': 'u2028',
 
1090
    '\u2029': 'u2029'
 
1091
  };
 
1092
 
 
1093
  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
 
1094
 
 
1095
  // JavaScript micro-templating, similar to John Resig's implementation.
 
1096
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
 
1097
  // and correctly escapes quotes within interpolated code.
 
1098
  _.template = function(text, data, settings) {
 
1099
    settings = _.defaults({}, settings, _.templateSettings);
 
1100
 
 
1101
    // Combine delimiters into one regular expression via alternation.
 
1102
    var matcher = new RegExp([
 
1103
      (settings.escape || noMatch).source,
 
1104
      (settings.interpolate || noMatch).source,
 
1105
      (settings.evaluate || noMatch).source
 
1106
    ].join('|') + '|$', 'g');
 
1107
 
 
1108
    // Compile the template source, escaping string literals appropriately.
 
1109
    var index = 0;
 
1110
    var source = "__p+='";
 
1111
    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
 
1112
      source += text.slice(index, offset)
 
1113
        .replace(escaper, function(match) { return '\\' + escapes[match]; });
 
1114
      source +=
 
1115
        escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
 
1116
        interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
 
1117
        evaluate ? "';\n" + evaluate + "\n__p+='" : '';
 
1118
      index = offset + match.length;
 
1119
    });
 
1120
    source += "';\n";
 
1121
 
 
1122
    // If a variable is not specified, place data values in local scope.
 
1123
    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
 
1124
 
 
1125
    source = "var __t,__p='',__j=Array.prototype.join," +
 
1126
      "print=function(){__p+=__j.call(arguments,'');};\n" +
 
1127
      source + "return __p;\n";
 
1128
 
 
1129
    try {
 
1130
      var render = new Function(settings.variable || 'obj', '_', source);
 
1131
    } catch (e) {
 
1132
      e.source = source;
 
1133
      throw e;
 
1134
    }
 
1135
 
 
1136
    if (data) return render(data, _);
 
1137
    var template = function(data) {
 
1138
      return render.call(this, data, _);
 
1139
    };
 
1140
 
 
1141
    // Provide the compiled function source as a convenience for precompilation.
 
1142
    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
 
1143
 
 
1144
    return template;
 
1145
  };
 
1146
 
 
1147
  // Add a "chain" function, which will delegate to the wrapper.
 
1148
  _.chain = function(obj) {
 
1149
    return _(obj).chain();
 
1150
  };
 
1151
 
 
1152
  // OOP
 
1153
  // ---------------
 
1154
  // If Underscore is called as a function, it returns a wrapped object that
 
1155
  // can be used OO-style. This wrapper holds altered versions of all the
 
1156
  // underscore functions. Wrapped objects may be chained.
 
1157
 
 
1158
  // Helper function to continue chaining intermediate results.
 
1159
  var result = function(obj) {
 
1160
    return this._chain ? _(obj).chain() : obj;
 
1161
  };
 
1162
 
 
1163
  // Add all of the Underscore functions to the wrapper object.
 
1164
  _.mixin(_);
 
1165
 
 
1166
  // Add all mutator Array functions to the wrapper.
 
1167
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
 
1168
    var method = ArrayProto[name];
 
1169
    _.prototype[name] = function() {
 
1170
      var obj = this._wrapped;
 
1171
      method.apply(obj, arguments);
 
1172
      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
 
1173
      return result.call(this, obj);
 
1174
    };
 
1175
  });
 
1176
 
 
1177
  // Add all accessor Array functions to the wrapper.
 
1178
  each(['concat', 'join', 'slice'], function(name) {
 
1179
    var method = ArrayProto[name];
 
1180
    _.prototype[name] = function() {
 
1181
      return result.call(this, method.apply(this._wrapped, arguments));
 
1182
    };
 
1183
  });
 
1184
 
 
1185
  _.extend(_.prototype, {
 
1186
 
 
1187
    // Start chaining a wrapped Underscore object.
 
1188
    chain: function() {
 
1189
      this._chain = true;
 
1190
      return this;
 
1191
    },
 
1192
 
 
1193
    // Extracts the result from a wrapped and chained object.
 
1194
    value: function() {
 
1195
      return this._wrapped;
 
1196
    }
 
1197
 
 
1198
  });
 
1199
 
 
1200
//}).call(this);