backbone-support 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,45 +1,33 @@
1
- // Underscore.js 1.4.4
2
- // ===================
1
+ // Underscore.js 1.7.0
2
+ // http://underscorejs.org
3
+ // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4
+ // Underscore may be freely distributed under the MIT license.
3
5
 
4
- // > http://underscorejs.org
5
- // > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
6
- // > Underscore may be freely distributed under the MIT license.
7
-
8
- // Baseline setup
9
- // --------------
10
6
  (function() {
11
7
 
12
- // Establish the root object, `window` in the browser, or `global` on the server.
8
+ // Baseline setup
9
+ // --------------
10
+
11
+ // Establish the root object, `window` in the browser, or `exports` on the server.
13
12
  var root = this;
14
13
 
15
14
  // Save the previous value of the `_` variable.
16
15
  var previousUnderscore = root._;
17
16
 
18
- // Establish the object that gets returned to break out of a loop iteration.
19
- var breaker = {};
20
-
21
17
  // Save bytes in the minified (but not gzipped) version:
22
18
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
23
19
 
24
20
  // Create quick reference variables for speed access to core prototypes.
25
- var push = ArrayProto.push,
26
- slice = ArrayProto.slice,
27
- concat = ArrayProto.concat,
28
- toString = ObjProto.toString,
29
- hasOwnProperty = ObjProto.hasOwnProperty;
21
+ var
22
+ push = ArrayProto.push,
23
+ slice = ArrayProto.slice,
24
+ concat = ArrayProto.concat,
25
+ toString = ObjProto.toString,
26
+ hasOwnProperty = ObjProto.hasOwnProperty;
30
27
 
31
28
  // All **ECMAScript 5** native function implementations that we hope to use
32
29
  // are declared here.
33
30
  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
31
  nativeIsArray = Array.isArray,
44
32
  nativeKeys = Object.keys,
45
33
  nativeBind = FuncProto.bind;
@@ -53,8 +41,7 @@
53
41
 
54
42
  // Export the Underscore object for **Node.js**, with
55
43
  // 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.
44
+ // the browser, add `_` as a global object.
58
45
  if (typeof exports !== 'undefined') {
59
46
  if (typeof module !== 'undefined' && module.exports) {
60
47
  exports = module.exports = _;
@@ -65,98 +52,125 @@
65
52
  }
66
53
 
67
54
  // Current version.
68
- _.VERSION = '1.4.4';
55
+ _.VERSION = '1.7.0';
56
+
57
+ // Internal function that returns an efficient (for current engines) version
58
+ // of the passed-in callback, to be repeatedly applied in other Underscore
59
+ // functions.
60
+ var createCallback = function(func, context, argCount) {
61
+ if (context === void 0) return func;
62
+ switch (argCount == null ? 3 : argCount) {
63
+ case 1: return function(value) {
64
+ return func.call(context, value);
65
+ };
66
+ case 2: return function(value, other) {
67
+ return func.call(context, value, other);
68
+ };
69
+ case 3: return function(value, index, collection) {
70
+ return func.call(context, value, index, collection);
71
+ };
72
+ case 4: return function(accumulator, value, index, collection) {
73
+ return func.call(context, accumulator, value, index, collection);
74
+ };
75
+ }
76
+ return function() {
77
+ return func.apply(context, arguments);
78
+ };
79
+ };
80
+
81
+ // A mostly-internal function to generate callbacks that can be applied
82
+ // to each element in a collection, returning the desired result — either
83
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
84
+ _.iteratee = function(value, context, argCount) {
85
+ if (value == null) return _.identity;
86
+ if (_.isFunction(value)) return createCallback(value, context, argCount);
87
+ if (_.isObject(value)) return _.matches(value);
88
+ return _.property(value);
89
+ };
69
90
 
70
91
  // Collection Functions
71
92
  // --------------------
72
93
 
73
94
  // 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;
95
+ // Handles raw objects in addition to array-likes. Treats all
96
+ // sparse array-likes as if they were dense.
97
+ _.each = _.forEach = function(obj, iteratee, context) {
98
+ if (obj == null) return obj;
99
+ iteratee = createCallback(iteratee, context);
100
+ var i, length = obj.length;
101
+ if (length === +length) {
102
+ for (i = 0; i < length; i++) {
103
+ iteratee(obj[i], i, obj);
83
104
  }
84
105
  } else {
85
- for (var key in obj) {
86
- if (_.has(obj, key)) {
87
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
88
- }
106
+ var keys = _.keys(obj);
107
+ for (i = 0, length = keys.length; i < length; i++) {
108
+ iteratee(obj[keys[i]], keys[i], obj);
89
109
  }
90
110
  }
111
+ return obj;
91
112
  };
92
113
 
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
- });
114
+ // Return the results of applying the iteratee to each element.
115
+ _.map = _.collect = function(obj, iteratee, context) {
116
+ if (obj == null) return [];
117
+ iteratee = _.iteratee(iteratee, context);
118
+ var keys = obj.length !== +obj.length && _.keys(obj),
119
+ length = (keys || obj).length,
120
+ results = Array(length),
121
+ currentKey;
122
+ for (var index = 0; index < length; index++) {
123
+ currentKey = keys ? keys[index] : index;
124
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
125
+ }
102
126
  return results;
103
127
  };
104
128
 
105
129
  var reduceError = 'Reduce of empty array with no initial value';
106
130
 
107
131
  // **Reduce** builds up a single result from a list of values, aka `inject`,
108
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
109
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
110
- var initial = arguments.length > 2;
132
+ // or `foldl`.
133
+ _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
111
134
  if (obj == null) obj = [];
112
- if (nativeReduce && obj.reduce === nativeReduce) {
113
- if (context) iterator = _.bind(iterator, context);
114
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
135
+ iteratee = createCallback(iteratee, context, 4);
136
+ var keys = obj.length !== +obj.length && _.keys(obj),
137
+ length = (keys || obj).length,
138
+ index = 0, currentKey;
139
+ if (arguments.length < 3) {
140
+ if (!length) throw new TypeError(reduceError);
141
+ memo = obj[keys ? keys[index++] : index++];
142
+ }
143
+ for (; index < length; index++) {
144
+ currentKey = keys ? keys[index] : index;
145
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
115
146
  }
116
- each(obj, function(value, index, list) {
117
- if (!initial) {
118
- memo = value;
119
- initial = true;
120
- } else {
121
- memo = iterator.call(context, memo, value, index, list);
122
- }
123
- });
124
- if (!initial) throw new TypeError(reduceError);
125
147
  return memo;
126
148
  };
127
149
 
128
150
  // The right-associative version of reduce, also known as `foldr`.
129
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
130
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
131
- var initial = arguments.length > 2;
151
+ _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
132
152
  if (obj == null) obj = [];
133
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
134
- if (context) iterator = _.bind(iterator, context);
135
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
153
+ iteratee = createCallback(iteratee, context, 4);
154
+ var keys = obj.length !== + obj.length && _.keys(obj),
155
+ index = (keys || obj).length,
156
+ currentKey;
157
+ if (arguments.length < 3) {
158
+ if (!index) throw new TypeError(reduceError);
159
+ memo = obj[keys ? keys[--index] : --index];
136
160
  }
137
- var length = obj.length;
138
- if (length !== +length) {
139
- var keys = _.keys(obj);
140
- length = keys.length;
161
+ while (index--) {
162
+ currentKey = keys ? keys[index] : index;
163
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
141
164
  }
142
- each(obj, function(value, index, list) {
143
- index = keys ? keys[--length] : --length;
144
- if (!initial) {
145
- memo = obj[index];
146
- initial = true;
147
- } else {
148
- memo = iterator.call(context, memo, obj[index], index, list);
149
- }
150
- });
151
- if (!initial) throw new TypeError(reduceError);
152
165
  return memo;
153
166
  };
154
167
 
155
168
  // Return the first value which passes a truth test. Aliased as `detect`.
156
- _.find = _.detect = function(obj, iterator, context) {
169
+ _.find = _.detect = function(obj, predicate, context) {
157
170
  var result;
158
- any(obj, function(value, index, list) {
159
- if (iterator.call(context, value, index, list)) {
171
+ predicate = _.iteratee(predicate, context);
172
+ _.some(obj, function(value, index, list) {
173
+ if (predicate(value, index, list)) {
160
174
  result = value;
161
175
  return true;
162
176
  }
@@ -165,61 +179,58 @@
165
179
  };
166
180
 
167
181
  // Return all the elements that pass a truth test.
168
- // Delegates to **ECMAScript 5**'s native `filter` if available.
169
182
  // Aliased as `select`.
170
- _.filter = _.select = function(obj, iterator, context) {
183
+ _.filter = _.select = function(obj, predicate, context) {
171
184
  var results = [];
172
185
  if (obj == null) return results;
173
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
174
- each(obj, function(value, index, list) {
175
- if (iterator.call(context, value, index, list)) results[results.length] = value;
186
+ predicate = _.iteratee(predicate, context);
187
+ _.each(obj, function(value, index, list) {
188
+ if (predicate(value, index, list)) results.push(value);
176
189
  });
177
190
  return results;
178
191
  };
179
192
 
180
193
  // Return all the elements for which a truth test fails.
181
- _.reject = function(obj, iterator, context) {
182
- return _.filter(obj, function(value, index, list) {
183
- return !iterator.call(context, value, index, list);
184
- }, context);
194
+ _.reject = function(obj, predicate, context) {
195
+ return _.filter(obj, _.negate(_.iteratee(predicate)), context);
185
196
  };
186
197
 
187
198
  // Determine whether all of the elements match a truth test.
188
- // Delegates to **ECMAScript 5**'s native `every` if available.
189
199
  // Aliased as `all`.
190
- _.every = _.all = function(obj, iterator, context) {
191
- iterator || (iterator = _.identity);
192
- var result = true;
193
- if (obj == null) return result;
194
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
195
- each(obj, function(value, index, list) {
196
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
197
- });
198
- return !!result;
200
+ _.every = _.all = function(obj, predicate, context) {
201
+ if (obj == null) return true;
202
+ predicate = _.iteratee(predicate, context);
203
+ var keys = obj.length !== +obj.length && _.keys(obj),
204
+ length = (keys || obj).length,
205
+ index, currentKey;
206
+ for (index = 0; index < length; index++) {
207
+ currentKey = keys ? keys[index] : index;
208
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
209
+ }
210
+ return true;
199
211
  };
200
212
 
201
213
  // Determine if at least one element in the object matches a truth test.
202
- // Delegates to **ECMAScript 5**'s native `some` if available.
203
214
  // Aliased as `any`.
204
- var any = _.some = _.any = function(obj, iterator, context) {
205
- iterator || (iterator = _.identity);
206
- var result = false;
207
- if (obj == null) return result;
208
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
209
- each(obj, function(value, index, list) {
210
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
211
- });
212
- return !!result;
215
+ _.some = _.any = function(obj, predicate, context) {
216
+ if (obj == null) return false;
217
+ predicate = _.iteratee(predicate, context);
218
+ var keys = obj.length !== +obj.length && _.keys(obj),
219
+ length = (keys || obj).length,
220
+ index, currentKey;
221
+ for (index = 0; index < length; index++) {
222
+ currentKey = keys ? keys[index] : index;
223
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
224
+ }
225
+ return false;
213
226
  };
214
227
 
215
228
  // Determine if the array or object contains a given value (using `===`).
216
229
  // Aliased as `include`.
217
230
  _.contains = _.include = function(obj, target) {
218
231
  if (obj == null) return false;
219
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
220
- return any(obj, function(value) {
221
- return value === target;
222
- });
232
+ if (obj.length !== +obj.length) obj = _.values(obj);
233
+ return _.indexOf(obj, target) >= 0;
223
234
  };
224
235
 
225
236
  // Invoke a method (with arguments) on every item in a collection.
@@ -233,83 +244,104 @@
233
244
 
234
245
  // Convenience version of a common use case of `map`: fetching a property.
235
246
  _.pluck = function(obj, key) {
236
- return _.map(obj, function(value){ return value[key]; });
247
+ return _.map(obj, _.property(key));
237
248
  };
238
249
 
239
250
  // Convenience version of a common use case of `filter`: selecting only objects
240
251
  // containing specific `key:value` pairs.
241
- _.where = function(obj, attrs, first) {
242
- if (_.isEmpty(attrs)) return first ? null : [];
243
- return _[first ? 'find' : 'filter'](obj, function(value) {
244
- for (var key in attrs) {
245
- if (attrs[key] !== value[key]) return false;
246
- }
247
- return true;
248
- });
252
+ _.where = function(obj, attrs) {
253
+ return _.filter(obj, _.matches(attrs));
249
254
  };
250
255
 
251
256
  // Convenience version of a common use case of `find`: getting the first object
252
257
  // containing specific `key:value` pairs.
253
258
  _.findWhere = function(obj, attrs) {
254
- return _.where(obj, attrs, true);
255
- };
256
-
257
- // Return the maximum element or (element-based computation).
258
- // Can't optimize arrays of integers longer than 65,535 elements.
259
- // See: https://bugs.webkit.org/show_bug.cgi?id=80797
260
- _.max = function(obj, iterator, context) {
261
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
262
- return Math.max.apply(Math, obj);
259
+ return _.find(obj, _.matches(attrs));
260
+ };
261
+
262
+ // Return the maximum element (or element-based computation).
263
+ _.max = function(obj, iteratee, context) {
264
+ var result = -Infinity, lastComputed = -Infinity,
265
+ value, computed;
266
+ if (iteratee == null && obj != null) {
267
+ obj = obj.length === +obj.length ? obj : _.values(obj);
268
+ for (var i = 0, length = obj.length; i < length; i++) {
269
+ value = obj[i];
270
+ if (value > result) {
271
+ result = value;
272
+ }
273
+ }
274
+ } else {
275
+ iteratee = _.iteratee(iteratee, context);
276
+ _.each(obj, function(value, index, list) {
277
+ computed = iteratee(value, index, list);
278
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
279
+ result = value;
280
+ lastComputed = computed;
281
+ }
282
+ });
263
283
  }
264
- if (!iterator && _.isEmpty(obj)) return -Infinity;
265
- var result = {computed : -Infinity, value: -Infinity};
266
- each(obj, function(value, index, list) {
267
- var computed = iterator ? iterator.call(context, value, index, list) : value;
268
- computed >= result.computed && (result = {value : value, computed : computed});
269
- });
270
- return result.value;
284
+ return result;
271
285
  };
272
286
 
273
287
  // Return the minimum element (or element-based computation).
274
- _.min = function(obj, iterator, context) {
275
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
276
- return Math.min.apply(Math, obj);
288
+ _.min = function(obj, iteratee, context) {
289
+ var result = Infinity, lastComputed = Infinity,
290
+ value, computed;
291
+ if (iteratee == null && obj != null) {
292
+ obj = obj.length === +obj.length ? obj : _.values(obj);
293
+ for (var i = 0, length = obj.length; i < length; i++) {
294
+ value = obj[i];
295
+ if (value < result) {
296
+ result = value;
297
+ }
298
+ }
299
+ } else {
300
+ iteratee = _.iteratee(iteratee, context);
301
+ _.each(obj, function(value, index, list) {
302
+ computed = iteratee(value, index, list);
303
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
304
+ result = value;
305
+ lastComputed = computed;
306
+ }
307
+ });
277
308
  }
278
- if (!iterator && _.isEmpty(obj)) return Infinity;
279
- var result = {computed : Infinity, value: Infinity};
280
- each(obj, function(value, index, list) {
281
- var computed = iterator ? iterator.call(context, value, index, list) : value;
282
- computed < result.computed && (result = {value : value, computed : computed});
283
- });
284
- return result.value;
309
+ return result;
285
310
  };
286
311
 
287
- // Shuffle an array.
312
+ // Shuffle a collection, using the modern version of the
313
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
288
314
  _.shuffle = function(obj) {
289
- var rand;
290
- var index = 0;
291
- var shuffled = [];
292
- each(obj, function(value) {
293
- rand = _.random(index++);
294
- shuffled[index - 1] = shuffled[rand];
295
- shuffled[rand] = value;
296
- });
315
+ var set = obj && obj.length === +obj.length ? obj : _.values(obj);
316
+ var length = set.length;
317
+ var shuffled = Array(length);
318
+ for (var index = 0, rand; index < length; index++) {
319
+ rand = _.random(0, index);
320
+ if (rand !== index) shuffled[index] = shuffled[rand];
321
+ shuffled[rand] = set[index];
322
+ }
297
323
  return shuffled;
298
324
  };
299
325
 
300
- // An internal function to generate lookup iterators.
301
- var lookupIterator = function(value) {
302
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
326
+ // Sample **n** random values from a collection.
327
+ // If **n** is not specified, returns a single random element.
328
+ // The internal `guard` argument allows it to work with `map`.
329
+ _.sample = function(obj, n, guard) {
330
+ if (n == null || guard) {
331
+ if (obj.length !== +obj.length) obj = _.values(obj);
332
+ return obj[_.random(obj.length - 1)];
333
+ }
334
+ return _.shuffle(obj).slice(0, Math.max(0, n));
303
335
  };
304
336
 
305
- // Sort the object's values by a criterion produced by an iterator.
306
- _.sortBy = function(obj, value, context) {
307
- var iterator = lookupIterator(value);
337
+ // Sort the object's values by a criterion produced by an iteratee.
338
+ _.sortBy = function(obj, iteratee, context) {
339
+ iteratee = _.iteratee(iteratee, context);
308
340
  return _.pluck(_.map(obj, function(value, index, list) {
309
341
  return {
310
- value : value,
311
- index : index,
312
- criteria : iterator.call(context, value, index, list)
342
+ value: value,
343
+ index: index,
344
+ criteria: iteratee(value, index, list)
313
345
  };
314
346
  }).sort(function(left, right) {
315
347
  var a = left.criteria;
@@ -318,53 +350,56 @@
318
350
  if (a > b || a === void 0) return 1;
319
351
  if (a < b || b === void 0) return -1;
320
352
  }
321
- return left.index < right.index ? -1 : 1;
353
+ return left.index - right.index;
322
354
  }), 'value');
323
355
  };
324
356
 
325
357
  // An internal function used for aggregate "group by" operations.
326
- var group = function(obj, value, context, behavior) {
327
- var result = {};
328
- var iterator = lookupIterator(value || _.identity);
329
- each(obj, function(value, index) {
330
- var key = iterator.call(context, value, index, obj);
331
- behavior(result, key, value);
332
- });
333
- return result;
358
+ var group = function(behavior) {
359
+ return function(obj, iteratee, context) {
360
+ var result = {};
361
+ iteratee = _.iteratee(iteratee, context);
362
+ _.each(obj, function(value, index) {
363
+ var key = iteratee(value, index, obj);
364
+ behavior(result, value, key);
365
+ });
366
+ return result;
367
+ };
334
368
  };
335
369
 
336
370
  // Groups the object's values by a criterion. Pass either a string attribute
337
371
  // to group by, or a function that returns the criterion.
338
- _.groupBy = function(obj, value, context) {
339
- return group(obj, value, context, function(result, key, value) {
340
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
341
- });
342
- };
372
+ _.groupBy = group(function(result, value, key) {
373
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
374
+ });
375
+
376
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
377
+ // when you know that your index values will be unique.
378
+ _.indexBy = group(function(result, value, key) {
379
+ result[key] = value;
380
+ });
343
381
 
344
382
  // Counts instances of an object that group by a certain criterion. Pass
345
383
  // either a string attribute to count by, or a function that returns the
346
384
  // criterion.
347
- _.countBy = function(obj, value, context) {
348
- return group(obj, value, context, function(result, key) {
349
- if (!_.has(result, key)) result[key] = 0;
350
- result[key]++;
351
- });
352
- };
385
+ _.countBy = group(function(result, value, key) {
386
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
387
+ });
353
388
 
354
389
  // Use a comparator function to figure out the smallest index at which
355
390
  // an object should be inserted so as to maintain order. Uses binary search.
356
- _.sortedIndex = function(array, obj, iterator, context) {
357
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
358
- var value = iterator.call(context, obj);
391
+ _.sortedIndex = function(array, obj, iteratee, context) {
392
+ iteratee = _.iteratee(iteratee, context, 1);
393
+ var value = iteratee(obj);
359
394
  var low = 0, high = array.length;
360
395
  while (low < high) {
361
- var mid = (low + high) >>> 1;
362
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
396
+ var mid = low + high >>> 1;
397
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
363
398
  }
364
399
  return low;
365
400
  };
366
401
 
367
- // Safely convert anything iterable into a real, live array.
402
+ // Safely create a real, live array from anything iterable.
368
403
  _.toArray = function(obj) {
369
404
  if (!obj) return [];
370
405
  if (_.isArray(obj)) return slice.call(obj);
@@ -375,7 +410,18 @@
375
410
  // Return the number of elements in an object.
376
411
  _.size = function(obj) {
377
412
  if (obj == null) return 0;
378
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
413
+ return obj.length === +obj.length ? obj.length : _.keys(obj).length;
414
+ };
415
+
416
+ // Split a collection into two arrays: one whose elements all satisfy the given
417
+ // predicate, and one whose elements all do not satisfy the predicate.
418
+ _.partition = function(obj, predicate, context) {
419
+ predicate = _.iteratee(predicate, context);
420
+ var pass = [], fail = [];
421
+ _.each(obj, function(value, key, obj) {
422
+ (predicate(value, key, obj) ? pass : fail).push(value);
423
+ });
424
+ return [pass, fail];
379
425
  };
380
426
 
381
427
  // Array Functions
@@ -386,7 +432,9 @@
386
432
  // allows it to work with `_.map`.
387
433
  _.first = _.head = _.take = function(array, n, guard) {
388
434
  if (array == null) return void 0;
389
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
435
+ if (n == null || guard) return array[0];
436
+ if (n < 0) return [];
437
+ return slice.call(array, 0, n);
390
438
  };
391
439
 
392
440
  // Returns everything but the last entry of the array. Especially useful on
@@ -394,18 +442,15 @@
394
442
  // the array, excluding the last N. The **guard** check allows it to work with
395
443
  // `_.map`.
396
444
  _.initial = function(array, n, guard) {
397
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
445
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
398
446
  };
399
447
 
400
448
  // Get the last element of an array. Passing **n** will return the last N
401
449
  // values in the array. The **guard** check allows it to work with `_.map`.
402
450
  _.last = function(array, n, guard) {
403
451
  if (array == null) return void 0;
404
- if ((n != null) && !guard) {
405
- return slice.call(array, Math.max(array.length - n, 0));
406
- } else {
407
- return array[array.length - 1];
408
- }
452
+ if (n == null || guard) return array[array.length - 1];
453
+ return slice.call(array, Math.max(array.length - n, 0));
409
454
  };
410
455
 
411
456
  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
@@ -413,7 +458,7 @@
413
458
  // the rest N values in the array. The **guard**
414
459
  // check allows it to work with `_.map`.
415
460
  _.rest = _.tail = _.drop = function(array, n, guard) {
416
- return slice.call(array, (n == null) || guard ? 1 : n);
461
+ return slice.call(array, n == null || guard ? 1 : n);
417
462
  };
418
463
 
419
464
  // Trim out all falsy values from an array.
@@ -422,20 +467,26 @@
422
467
  };
423
468
 
424
469
  // Internal implementation of a recursive `flatten` function.
425
- var flatten = function(input, shallow, output) {
426
- each(input, function(value) {
427
- if (_.isArray(value)) {
428
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
470
+ var flatten = function(input, shallow, strict, output) {
471
+ if (shallow && _.every(input, _.isArray)) {
472
+ return concat.apply(output, input);
473
+ }
474
+ for (var i = 0, length = input.length; i < length; i++) {
475
+ var value = input[i];
476
+ if (!_.isArray(value) && !_.isArguments(value)) {
477
+ if (!strict) output.push(value);
478
+ } else if (shallow) {
479
+ push.apply(output, value);
429
480
  } else {
430
- output.push(value);
481
+ flatten(value, shallow, strict, output);
431
482
  }
432
- });
483
+ }
433
484
  return output;
434
485
  };
435
486
 
436
- // Return a completely flattened version of an array.
487
+ // Flatten out an array, either recursively (by default), or just one level.
437
488
  _.flatten = function(array, shallow) {
438
- return flatten(array, shallow, []);
489
+ return flatten(array, shallow, false, []);
439
490
  };
440
491
 
441
492
  // Return a version of the array that does not contain the specified value(s).
@@ -446,56 +497,74 @@
446
497
  // Produce a duplicate-free version of the array. If the array has already
447
498
  // been sorted, you have the option of using a faster algorithm.
448
499
  // Aliased as `unique`.
449
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
450
- if (_.isFunction(isSorted)) {
451
- context = iterator;
452
- iterator = isSorted;
500
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
501
+ if (array == null) return [];
502
+ if (!_.isBoolean(isSorted)) {
503
+ context = iteratee;
504
+ iteratee = isSorted;
453
505
  isSorted = false;
454
506
  }
455
- var initial = iterator ? _.map(array, iterator, context) : array;
456
- var results = [];
507
+ if (iteratee != null) iteratee = _.iteratee(iteratee, context);
508
+ var result = [];
457
509
  var seen = [];
458
- each(initial, function(value, index) {
459
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
460
- seen.push(value);
461
- results.push(array[index]);
510
+ for (var i = 0, length = array.length; i < length; i++) {
511
+ var value = array[i];
512
+ if (isSorted) {
513
+ if (!i || seen !== value) result.push(value);
514
+ seen = value;
515
+ } else if (iteratee) {
516
+ var computed = iteratee(value, i, array);
517
+ if (_.indexOf(seen, computed) < 0) {
518
+ seen.push(computed);
519
+ result.push(value);
520
+ }
521
+ } else if (_.indexOf(result, value) < 0) {
522
+ result.push(value);
462
523
  }
463
- });
464
- return results;
524
+ }
525
+ return result;
465
526
  };
466
527
 
467
528
  // Produce an array that contains the union: each distinct element from all of
468
529
  // the passed-in arrays.
469
530
  _.union = function() {
470
- return _.uniq(concat.apply(ArrayProto, arguments));
531
+ return _.uniq(flatten(arguments, true, true, []));
471
532
  };
472
533
 
473
534
  // Produce an array that contains every item shared between all the
474
535
  // passed-in arrays.
475
536
  _.intersection = function(array) {
476
- var rest = slice.call(arguments, 1);
477
- return _.filter(_.uniq(array), function(item) {
478
- return _.every(rest, function(other) {
479
- return _.indexOf(other, item) >= 0;
480
- });
481
- });
537
+ if (array == null) return [];
538
+ var result = [];
539
+ var argsLength = arguments.length;
540
+ for (var i = 0, length = array.length; i < length; i++) {
541
+ var item = array[i];
542
+ if (_.contains(result, item)) continue;
543
+ for (var j = 1; j < argsLength; j++) {
544
+ if (!_.contains(arguments[j], item)) break;
545
+ }
546
+ if (j === argsLength) result.push(item);
547
+ }
548
+ return result;
482
549
  };
483
550
 
484
551
  // Take the difference between one array and a number of other arrays.
485
552
  // Only the elements present in just the first array will remain.
486
553
  _.difference = function(array) {
487
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
488
- return _.filter(array, function(value){ return !_.contains(rest, value); });
554
+ var rest = flatten(slice.call(arguments, 1), true, true, []);
555
+ return _.filter(array, function(value){
556
+ return !_.contains(rest, value);
557
+ });
489
558
  };
490
559
 
491
560
  // Zip together multiple lists into a single array -- elements that share
492
561
  // an index go together.
493
- _.zip = function() {
494
- var args = slice.call(arguments);
495
- var length = _.max(_.pluck(args, 'length'));
496
- var results = new Array(length);
562
+ _.zip = function(array) {
563
+ if (array == null) return [];
564
+ var length = _.max(arguments, 'length').length;
565
+ var results = Array(length);
497
566
  for (var i = 0; i < length; i++) {
498
- results[i] = _.pluck(args, "" + i);
567
+ results[i] = _.pluck(arguments, i);
499
568
  }
500
569
  return results;
501
570
  };
@@ -506,7 +575,7 @@
506
575
  _.object = function(list, values) {
507
576
  if (list == null) return {};
508
577
  var result = {};
509
- for (var i = 0, l = list.length; i < l; i++) {
578
+ for (var i = 0, length = list.length; i < length; i++) {
510
579
  if (values) {
511
580
  result[list[i]] = values[i];
512
581
  } else {
@@ -516,37 +585,32 @@
516
585
  return result;
517
586
  };
518
587
 
519
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
520
- // we need this function. Return the position of the first occurrence of an
521
- // item in an array, or -1 if the item is not included in the array.
522
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
588
+ // Return the position of the first occurrence of an item in an array,
589
+ // or -1 if the item is not included in the array.
523
590
  // If the array is large and already in sort order, pass `true`
524
591
  // for **isSorted** to use binary search.
525
592
  _.indexOf = function(array, item, isSorted) {
526
593
  if (array == null) return -1;
527
- var i = 0, l = array.length;
594
+ var i = 0, length = array.length;
528
595
  if (isSorted) {
529
596
  if (typeof isSorted == 'number') {
530
- i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
597
+ i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
531
598
  } else {
532
599
  i = _.sortedIndex(array, item);
533
600
  return array[i] === item ? i : -1;
534
601
  }
535
602
  }
536
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
537
- for (; i < l; i++) if (array[i] === item) return i;
603
+ for (; i < length; i++) if (array[i] === item) return i;
538
604
  return -1;
539
605
  };
540
606
 
541
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
542
607
  _.lastIndexOf = function(array, item, from) {
543
608
  if (array == null) return -1;
544
- var hasIndex = from != null;
545
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
546
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
609
+ var idx = array.length;
610
+ if (typeof from == 'number') {
611
+ idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
547
612
  }
548
- var i = (hasIndex ? from : array.length);
549
- while (i--) if (array[i] === item) return i;
613
+ while (--idx >= 0) if (array[idx] === item) return idx;
550
614
  return -1;
551
615
  };
552
616
 
@@ -558,15 +622,13 @@
558
622
  stop = start || 0;
559
623
  start = 0;
560
624
  }
561
- step = arguments[2] || 1;
625
+ step = step || 1;
562
626
 
563
- var len = Math.max(Math.ceil((stop - start) / step), 0);
564
- var idx = 0;
565
- var range = new Array(len);
627
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
628
+ var range = Array(length);
566
629
 
567
- while(idx < len) {
568
- range[idx++] = start;
569
- start += step;
630
+ for (var idx = 0; idx < length; idx++, start += step) {
631
+ range[idx] = start;
570
632
  }
571
633
 
572
634
  return range;
@@ -575,50 +637,77 @@
575
637
  // Function (ahem) Functions
576
638
  // ------------------
577
639
 
640
+ // Reusable constructor function for prototype setting.
641
+ var Ctor = function(){};
642
+
578
643
  // Create a function bound to a given object (assigning `this`, and arguments,
579
644
  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
580
645
  // available.
581
646
  _.bind = function(func, context) {
582
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
583
- var args = slice.call(arguments, 2);
584
- return function() {
585
- return func.apply(context, args.concat(slice.call(arguments)));
647
+ var args, bound;
648
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
649
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
650
+ args = slice.call(arguments, 2);
651
+ bound = function() {
652
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
653
+ Ctor.prototype = func.prototype;
654
+ var self = new Ctor;
655
+ Ctor.prototype = null;
656
+ var result = func.apply(self, args.concat(slice.call(arguments)));
657
+ if (_.isObject(result)) return result;
658
+ return self;
586
659
  };
660
+ return bound;
587
661
  };
588
662
 
589
663
  // Partially apply a function by creating a version that has had some of its
590
- // arguments pre-filled, without changing its dynamic `this` context.
664
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
665
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
591
666
  _.partial = function(func) {
592
- var args = slice.call(arguments, 1);
667
+ var boundArgs = slice.call(arguments, 1);
593
668
  return function() {
594
- return func.apply(this, args.concat(slice.call(arguments)));
669
+ var position = 0;
670
+ var args = boundArgs.slice();
671
+ for (var i = 0, length = args.length; i < length; i++) {
672
+ if (args[i] === _) args[i] = arguments[position++];
673
+ }
674
+ while (position < arguments.length) args.push(arguments[position++]);
675
+ return func.apply(this, args);
595
676
  };
596
677
  };
597
678
 
598
- // Bind all of an object's methods to that object. Useful for ensuring that
599
- // all callbacks defined on an object belong to it.
679
+ // Bind a number of an object's methods to that object. Remaining arguments
680
+ // are the method names to be bound. Useful for ensuring that all callbacks
681
+ // defined on an object belong to it.
600
682
  _.bindAll = function(obj) {
601
- var funcs = slice.call(arguments, 1);
602
- if (funcs.length === 0) funcs = _.functions(obj);
603
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
683
+ var i, length = arguments.length, key;
684
+ if (length <= 1) throw new Error('bindAll must be passed function names');
685
+ for (i = 1; i < length; i++) {
686
+ key = arguments[i];
687
+ obj[key] = _.bind(obj[key], obj);
688
+ }
604
689
  return obj;
605
690
  };
606
691
 
607
692
  // Memoize an expensive function by storing its results.
608
693
  _.memoize = function(func, hasher) {
609
- var memo = {};
610
- hasher || (hasher = _.identity);
611
- return function() {
612
- var key = hasher.apply(this, arguments);
613
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
694
+ var memoize = function(key) {
695
+ var cache = memoize.cache;
696
+ var address = hasher ? hasher.apply(this, arguments) : key;
697
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
698
+ return cache[address];
614
699
  };
700
+ memoize.cache = {};
701
+ return memoize;
615
702
  };
616
703
 
617
704
  // Delays a function for the given number of milliseconds, and then calls
618
705
  // it with the arguments supplied.
619
706
  _.delay = function(func, wait) {
620
707
  var args = slice.call(arguments, 2);
621
- return setTimeout(function(){ return func.apply(null, args); }, wait);
708
+ return setTimeout(function(){
709
+ return func.apply(null, args);
710
+ }, wait);
622
711
  };
623
712
 
624
713
  // Defers a function, scheduling it to run after the current call stack has
@@ -628,26 +717,34 @@
628
717
  };
629
718
 
630
719
  // Returns a function, that, when invoked, will only be triggered at most once
631
- // during a given window of time.
632
- _.throttle = function(func, wait) {
633
- var context, args, timeout, result;
720
+ // during a given window of time. Normally, the throttled function will run
721
+ // as much as it can, without ever going more than once per `wait` duration;
722
+ // but if you'd like to disable the execution on the leading edge, pass
723
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
724
+ _.throttle = function(func, wait, options) {
725
+ var context, args, result;
726
+ var timeout = null;
634
727
  var previous = 0;
728
+ if (!options) options = {};
635
729
  var later = function() {
636
- previous = new Date;
730
+ previous = options.leading === false ? 0 : _.now();
637
731
  timeout = null;
638
732
  result = func.apply(context, args);
733
+ if (!timeout) context = args = null;
639
734
  };
640
735
  return function() {
641
- var now = new Date;
736
+ var now = _.now();
737
+ if (!previous && options.leading === false) previous = now;
642
738
  var remaining = wait - (now - previous);
643
739
  context = this;
644
740
  args = arguments;
645
- if (remaining <= 0) {
741
+ if (remaining <= 0 || remaining > wait) {
646
742
  clearTimeout(timeout);
647
743
  timeout = null;
648
744
  previous = now;
649
745
  result = func.apply(context, args);
650
- } else if (!timeout) {
746
+ if (!timeout) context = args = null;
747
+ } else if (!timeout && options.trailing !== false) {
651
748
  timeout = setTimeout(later, remaining);
652
749
  }
653
750
  return result;
@@ -659,31 +756,34 @@
659
756
  // N milliseconds. If `immediate` is passed, trigger the function on the
660
757
  // leading edge, instead of the trailing.
661
758
  _.debounce = function(func, wait, immediate) {
662
- var timeout, result;
663
- return function() {
664
- var context = this, args = arguments;
665
- var later = function() {
759
+ var timeout, args, context, timestamp, result;
760
+
761
+ var later = function() {
762
+ var last = _.now() - timestamp;
763
+
764
+ if (last < wait && last > 0) {
765
+ timeout = setTimeout(later, wait - last);
766
+ } else {
666
767
  timeout = null;
667
- if (!immediate) result = func.apply(context, args);
668
- };
669
- var callNow = immediate && !timeout;
670
- clearTimeout(timeout);
671
- timeout = setTimeout(later, wait);
672
- if (callNow) result = func.apply(context, args);
673
- return result;
768
+ if (!immediate) {
769
+ result = func.apply(context, args);
770
+ if (!timeout) context = args = null;
771
+ }
772
+ }
674
773
  };
675
- };
676
774
 
677
- // Returns a function that will be executed at most one time, no matter how
678
- // often you call it. Useful for lazy initialization.
679
- _.once = function(func) {
680
- var ran = false, memo;
681
775
  return function() {
682
- if (ran) return memo;
683
- ran = true;
684
- memo = func.apply(this, arguments);
685
- func = null;
686
- return memo;
776
+ context = this;
777
+ args = arguments;
778
+ timestamp = _.now();
779
+ var callNow = immediate && !timeout;
780
+ if (!timeout) timeout = setTimeout(later, wait);
781
+ if (callNow) {
782
+ result = func.apply(context, args);
783
+ context = args = null;
784
+ }
785
+
786
+ return result;
687
787
  };
688
788
  };
689
789
 
@@ -691,29 +791,31 @@
691
791
  // allowing you to adjust arguments, run code before and after, and
692
792
  // conditionally execute the original function.
693
793
  _.wrap = function(func, wrapper) {
794
+ return _.partial(wrapper, func);
795
+ };
796
+
797
+ // Returns a negated version of the passed-in predicate.
798
+ _.negate = function(predicate) {
694
799
  return function() {
695
- var args = [func];
696
- push.apply(args, arguments);
697
- return wrapper.apply(this, args);
800
+ return !predicate.apply(this, arguments);
698
801
  };
699
802
  };
700
803
 
701
804
  // Returns a function that is the composition of a list of functions, each
702
805
  // consuming the return value of the function that follows.
703
806
  _.compose = function() {
704
- var funcs = arguments;
807
+ var args = arguments;
808
+ var start = args.length - 1;
705
809
  return function() {
706
- var args = arguments;
707
- for (var i = funcs.length - 1; i >= 0; i--) {
708
- args = [funcs[i].apply(this, args)];
709
- }
710
- return args[0];
810
+ var i = start;
811
+ var result = args[start].apply(this, arguments);
812
+ while (i--) result = args[i].call(this, result);
813
+ return result;
711
814
  };
712
815
  };
713
816
 
714
817
  // Returns a function that will only be executed after being called N times.
715
818
  _.after = function(times, func) {
716
- if (times <= 0) return func();
717
819
  return function() {
718
820
  if (--times < 1) {
719
821
  return func.apply(this, arguments);
@@ -721,36 +823,65 @@
721
823
  };
722
824
  };
723
825
 
826
+ // Returns a function that will only be executed before being called N times.
827
+ _.before = function(times, func) {
828
+ var memo;
829
+ return function() {
830
+ if (--times > 0) {
831
+ memo = func.apply(this, arguments);
832
+ } else {
833
+ func = null;
834
+ }
835
+ return memo;
836
+ };
837
+ };
838
+
839
+ // Returns a function that will be executed at most one time, no matter how
840
+ // often you call it. Useful for lazy initialization.
841
+ _.once = _.partial(_.before, 2);
842
+
724
843
  // Object Functions
725
844
  // ----------------
726
845
 
727
846
  // Retrieve the names of an object's properties.
728
847
  // Delegates to **ECMAScript 5**'s native `Object.keys`
729
- _.keys = nativeKeys || function(obj) {
730
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
848
+ _.keys = function(obj) {
849
+ if (!_.isObject(obj)) return [];
850
+ if (nativeKeys) return nativeKeys(obj);
731
851
  var keys = [];
732
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
852
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
733
853
  return keys;
734
854
  };
735
855
 
736
856
  // Retrieve the values of an object's properties.
737
857
  _.values = function(obj) {
738
- var values = [];
739
- for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
858
+ var keys = _.keys(obj);
859
+ var length = keys.length;
860
+ var values = Array(length);
861
+ for (var i = 0; i < length; i++) {
862
+ values[i] = obj[keys[i]];
863
+ }
740
864
  return values;
741
865
  };
742
866
 
743
867
  // Convert an object into a list of `[key, value]` pairs.
744
868
  _.pairs = function(obj) {
745
- var pairs = [];
746
- for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
869
+ var keys = _.keys(obj);
870
+ var length = keys.length;
871
+ var pairs = Array(length);
872
+ for (var i = 0; i < length; i++) {
873
+ pairs[i] = [keys[i], obj[keys[i]]];
874
+ }
747
875
  return pairs;
748
876
  };
749
877
 
750
878
  // Invert the keys and values of an object. The values must be serializable.
751
879
  _.invert = function(obj) {
752
880
  var result = {};
753
- for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
881
+ var keys = _.keys(obj);
882
+ for (var i = 0, length = keys.length; i < length; i++) {
883
+ result[obj[keys[i]]] = keys[i];
884
+ }
754
885
  return result;
755
886
  };
756
887
 
@@ -766,45 +897,62 @@
766
897
 
767
898
  // Extend a given object with all the properties in passed-in object(s).
768
899
  _.extend = function(obj) {
769
- each(slice.call(arguments, 1), function(source) {
770
- if (source) {
771
- for (var prop in source) {
772
- obj[prop] = source[prop];
900
+ if (!_.isObject(obj)) return obj;
901
+ var source, prop;
902
+ for (var i = 1, length = arguments.length; i < length; i++) {
903
+ source = arguments[i];
904
+ for (prop in source) {
905
+ if (hasOwnProperty.call(source, prop)) {
906
+ obj[prop] = source[prop];
773
907
  }
774
908
  }
775
- });
909
+ }
776
910
  return obj;
777
911
  };
778
912
 
779
913
  // Return a copy of the object only containing the whitelisted properties.
780
- _.pick = function(obj) {
781
- var copy = {};
782
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
783
- each(keys, function(key) {
784
- if (key in obj) copy[key] = obj[key];
785
- });
786
- return copy;
914
+ _.pick = function(obj, iteratee, context) {
915
+ var result = {}, key;
916
+ if (obj == null) return result;
917
+ if (_.isFunction(iteratee)) {
918
+ iteratee = createCallback(iteratee, context);
919
+ for (key in obj) {
920
+ var value = obj[key];
921
+ if (iteratee(value, key, obj)) result[key] = value;
922
+ }
923
+ } else {
924
+ var keys = concat.apply([], slice.call(arguments, 1));
925
+ obj = new Object(obj);
926
+ for (var i = 0, length = keys.length; i < length; i++) {
927
+ key = keys[i];
928
+ if (key in obj) result[key] = obj[key];
929
+ }
930
+ }
931
+ return result;
787
932
  };
788
933
 
789
934
  // Return a copy of the object without the blacklisted properties.
790
- _.omit = function(obj) {
791
- var copy = {};
792
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
793
- for (var key in obj) {
794
- if (!_.contains(keys, key)) copy[key] = obj[key];
935
+ _.omit = function(obj, iteratee, context) {
936
+ if (_.isFunction(iteratee)) {
937
+ iteratee = _.negate(iteratee);
938
+ } else {
939
+ var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
940
+ iteratee = function(value, key) {
941
+ return !_.contains(keys, key);
942
+ };
795
943
  }
796
- return copy;
944
+ return _.pick(obj, iteratee, context);
797
945
  };
798
946
 
799
947
  // Fill in a given object with default properties.
800
948
  _.defaults = function(obj) {
801
- each(slice.call(arguments, 1), function(source) {
802
- if (source) {
803
- for (var prop in source) {
804
- if (obj[prop] == null) obj[prop] = source[prop];
805
- }
949
+ if (!_.isObject(obj)) return obj;
950
+ for (var i = 1, length = arguments.length; i < length; i++) {
951
+ var source = arguments[i];
952
+ for (var prop in source) {
953
+ if (obj[prop] === void 0) obj[prop] = source[prop];
806
954
  }
807
- });
955
+ }
808
956
  return obj;
809
957
  };
810
958
 
@@ -825,8 +973,8 @@
825
973
  // Internal recursive comparison function for `isEqual`.
826
974
  var eq = function(a, b, aStack, bStack) {
827
975
  // Identical objects are equal. `0 === -0`, but they aren't identical.
828
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
829
- if (a === b) return a !== 0 || 1 / a == 1 / b;
976
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
977
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
830
978
  // A strict comparison is necessary because `null == undefined`.
831
979
  if (a == null || b == null) return a === b;
832
980
  // Unwrap any wrapped objects.
@@ -834,29 +982,27 @@
834
982
  if (b instanceof _) b = b._wrapped;
835
983
  // Compare `[[Class]]` names.
836
984
  var className = toString.call(a);
837
- if (className != toString.call(b)) return false;
985
+ if (className !== toString.call(b)) return false;
838
986
  switch (className) {
839
- // Strings, numbers, dates, and booleans are compared by value.
987
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
988
+ case '[object RegExp]':
989
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
840
990
  case '[object String]':
841
991
  // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
842
992
  // equivalent to `new String("5")`.
843
- return a == String(b);
993
+ return '' + a === '' + b;
844
994
  case '[object Number]':
845
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
846
- // other numeric values.
847
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
995
+ // `NaN`s are equivalent, but non-reflexive.
996
+ // Object(NaN) is equivalent to NaN
997
+ if (+a !== +a) return +b !== +b;
998
+ // An `egal` comparison is performed for other numeric values.
999
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
848
1000
  case '[object Date]':
849
1001
  case '[object Boolean]':
850
1002
  // Coerce dates and booleans to numeric primitive values. Dates are compared by their
851
1003
  // millisecond representations. Note that invalid dates with millisecond representations
852
1004
  // of `NaN` are not equivalent.
853
- return +a == +b;
854
- // RegExps are compared by their source patterns and flags.
855
- case '[object RegExp]':
856
- return a.source == b.source &&
857
- a.global == b.global &&
858
- a.multiline == b.multiline &&
859
- a.ignoreCase == b.ignoreCase;
1005
+ return +a === +b;
860
1006
  }
861
1007
  if (typeof a != 'object' || typeof b != 'object') return false;
862
1008
  // Assume equality for cyclic structures. The algorithm for detecting cyclic
@@ -865,17 +1011,29 @@
865
1011
  while (length--) {
866
1012
  // Linear search. Performance is inversely proportional to the number of
867
1013
  // unique nested structures.
868
- if (aStack[length] == a) return bStack[length] == b;
1014
+ if (aStack[length] === a) return bStack[length] === b;
1015
+ }
1016
+ // Objects with different constructors are not equivalent, but `Object`s
1017
+ // from different frames are.
1018
+ var aCtor = a.constructor, bCtor = b.constructor;
1019
+ if (
1020
+ aCtor !== bCtor &&
1021
+ // Handle Object.create(x) cases
1022
+ 'constructor' in a && 'constructor' in b &&
1023
+ !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
1024
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
1025
+ ) {
1026
+ return false;
869
1027
  }
870
1028
  // Add the first object to the stack of traversed objects.
871
1029
  aStack.push(a);
872
1030
  bStack.push(b);
873
- var size = 0, result = true;
1031
+ var size, result;
874
1032
  // Recursively compare objects and arrays.
875
- if (className == '[object Array]') {
1033
+ if (className === '[object Array]') {
876
1034
  // Compare array lengths to determine if a deep comparison is necessary.
877
1035
  size = a.length;
878
- result = size == b.length;
1036
+ result = size === b.length;
879
1037
  if (result) {
880
1038
  // Deep compare the contents, ignoring non-numeric properties.
881
1039
  while (size--) {
@@ -883,28 +1041,17 @@
883
1041
  }
884
1042
  }
885
1043
  } else {
886
- // Objects with different constructors are not equivalent, but `Object`s
887
- // from different frames are.
888
- var aCtor = a.constructor, bCtor = b.constructor;
889
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
890
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
891
- return false;
892
- }
893
1044
  // Deep compare objects.
894
- for (var key in a) {
895
- if (_.has(a, key)) {
896
- // Count the expected number of properties.
897
- size++;
898
- // Deep compare each member.
899
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
900
- }
901
- }
902
- // Ensure that both objects contain the same number of properties.
1045
+ var keys = _.keys(a), key;
1046
+ size = keys.length;
1047
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
1048
+ result = _.keys(b).length === size;
903
1049
  if (result) {
904
- for (key in b) {
905
- if (_.has(b, key) && !(size--)) break;
1050
+ while (size--) {
1051
+ // Deep compare each member
1052
+ key = keys[size];
1053
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
906
1054
  }
907
- result = !size;
908
1055
  }
909
1056
  }
910
1057
  // Remove the first object from the stack of traversed objects.
@@ -922,7 +1069,7 @@
922
1069
  // An "empty" object has no enumerable own-properties.
923
1070
  _.isEmpty = function(obj) {
924
1071
  if (obj == null) return true;
925
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
1072
+ if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
926
1073
  for (var key in obj) if (_.has(obj, key)) return false;
927
1074
  return true;
928
1075
  };
@@ -935,18 +1082,19 @@
935
1082
  // Is a given value an array?
936
1083
  // Delegates to ECMA5's native Array.isArray
937
1084
  _.isArray = nativeIsArray || function(obj) {
938
- return toString.call(obj) == '[object Array]';
1085
+ return toString.call(obj) === '[object Array]';
939
1086
  };
940
1087
 
941
1088
  // Is a given variable an object?
942
1089
  _.isObject = function(obj) {
943
- return obj === Object(obj);
1090
+ var type = typeof obj;
1091
+ return type === 'function' || type === 'object' && !!obj;
944
1092
  };
945
1093
 
946
1094
  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
947
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
1095
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
948
1096
  _['is' + name] = function(obj) {
949
- return toString.call(obj) == '[object ' + name + ']';
1097
+ return toString.call(obj) === '[object ' + name + ']';
950
1098
  };
951
1099
  });
952
1100
 
@@ -954,14 +1102,14 @@
954
1102
  // there isn't any inspectable "Arguments" type.
955
1103
  if (!_.isArguments(arguments)) {
956
1104
  _.isArguments = function(obj) {
957
- return !!(obj && _.has(obj, 'callee'));
1105
+ return _.has(obj, 'callee');
958
1106
  };
959
1107
  }
960
1108
 
961
- // Optimize `isFunction` if appropriate.
962
- if (typeof (/./) !== 'function') {
1109
+ // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
1110
+ if (typeof /./ !== 'function') {
963
1111
  _.isFunction = function(obj) {
964
- return typeof obj === 'function';
1112
+ return typeof obj == 'function' || false;
965
1113
  };
966
1114
  }
967
1115
 
@@ -972,12 +1120,12 @@
972
1120
 
973
1121
  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
974
1122
  _.isNaN = function(obj) {
975
- return _.isNumber(obj) && obj != +obj;
1123
+ return _.isNumber(obj) && obj !== +obj;
976
1124
  };
977
1125
 
978
1126
  // Is a given value a boolean?
979
1127
  _.isBoolean = function(obj) {
980
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
1128
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
981
1129
  };
982
1130
 
983
1131
  // Is a given value equal to null?
@@ -993,7 +1141,7 @@
993
1141
  // Shortcut function for checking if an object has a given property directly
994
1142
  // on itself (in other words, not on a prototype).
995
1143
  _.has = function(obj, key) {
996
- return hasOwnProperty.call(obj, key);
1144
+ return obj != null && hasOwnProperty.call(obj, key);
997
1145
  };
998
1146
 
999
1147
  // Utility Functions
@@ -1006,15 +1154,45 @@
1006
1154
  return this;
1007
1155
  };
1008
1156
 
1009
- // Keep the identity function around for default iterators.
1157
+ // Keep the identity function around for default iteratees.
1010
1158
  _.identity = function(value) {
1011
1159
  return value;
1012
1160
  };
1013
1161
 
1162
+ // Predicate-generating functions. Often useful outside of Underscore.
1163
+ _.constant = function(value) {
1164
+ return function() {
1165
+ return value;
1166
+ };
1167
+ };
1168
+
1169
+ _.noop = function(){};
1170
+
1171
+ _.property = function(key) {
1172
+ return function(obj) {
1173
+ return obj[key];
1174
+ };
1175
+ };
1176
+
1177
+ // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
1178
+ _.matches = function(attrs) {
1179
+ var pairs = _.pairs(attrs), length = pairs.length;
1180
+ return function(obj) {
1181
+ if (obj == null) return !length;
1182
+ obj = new Object(obj);
1183
+ for (var i = 0; i < length; i++) {
1184
+ var pair = pairs[i], key = pair[0];
1185
+ if (pair[1] !== obj[key] || !(key in obj)) return false;
1186
+ }
1187
+ return true;
1188
+ };
1189
+ };
1190
+
1014
1191
  // Run a function **n** times.
1015
- _.times = function(n, iterator, context) {
1016
- var accum = Array(n);
1017
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
1192
+ _.times = function(n, iteratee, context) {
1193
+ var accum = Array(Math.max(0, n));
1194
+ iteratee = createCallback(iteratee, context, 1);
1195
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
1018
1196
  return accum;
1019
1197
  };
1020
1198
 
@@ -1027,53 +1205,45 @@
1027
1205
  return min + Math.floor(Math.random() * (max - min + 1));
1028
1206
  };
1029
1207
 
1030
- // List of HTML entities for escaping.
1031
- var entityMap = {
1032
- escape: {
1033
- '&': '&amp;',
1034
- '<': '&lt;',
1035
- '>': '&gt;',
1036
- '"': '&quot;',
1037
- "'": '&#x27;',
1038
- '/': '&#x2F;'
1039
- }
1208
+ // A (possibly faster) way to get the current timestamp as an integer.
1209
+ _.now = Date.now || function() {
1210
+ return new Date().getTime();
1040
1211
  };
1041
- entityMap.unescape = _.invert(entityMap.escape);
1042
1212
 
1043
- // Regexes containing the keys and values listed immediately above.
1044
- var entityRegexes = {
1045
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
1046
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
1213
+ // List of HTML entities for escaping.
1214
+ var escapeMap = {
1215
+ '&': '&amp;',
1216
+ '<': '&lt;',
1217
+ '>': '&gt;',
1218
+ '"': '&quot;',
1219
+ "'": '&#x27;',
1220
+ '`': '&#x60;'
1047
1221
  };
1222
+ var unescapeMap = _.invert(escapeMap);
1048
1223
 
1049
1224
  // Functions for escaping and unescaping strings to/from HTML interpolation.
1050
- _.each(['escape', 'unescape'], function(method) {
1051
- _[method] = function(string) {
1052
- if (string == null) return '';
1053
- return ('' + string).replace(entityRegexes[method], function(match) {
1054
- return entityMap[method][match];
1055
- });
1225
+ var createEscaper = function(map) {
1226
+ var escaper = function(match) {
1227
+ return map[match];
1056
1228
  };
1057
- });
1229
+ // Regexes for identifying a key that needs to be escaped
1230
+ var source = '(?:' + _.keys(map).join('|') + ')';
1231
+ var testRegexp = RegExp(source);
1232
+ var replaceRegexp = RegExp(source, 'g');
1233
+ return function(string) {
1234
+ string = string == null ? '' : '' + string;
1235
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
1236
+ };
1237
+ };
1238
+ _.escape = createEscaper(escapeMap);
1239
+ _.unescape = createEscaper(unescapeMap);
1058
1240
 
1059
- // If the value of the named property is a function then invoke it;
1060
- // otherwise, return it.
1241
+ // If the value of the named `property` is a function then invoke it with the
1242
+ // `object` as context; otherwise, return it.
1061
1243
  _.result = function(object, property) {
1062
- if (object == null) return null;
1244
+ if (object == null) return void 0;
1063
1245
  var value = object[property];
1064
- return _.isFunction(value) ? value.call(object) : value;
1065
- };
1066
-
1067
- // Add your own custom functions to the Underscore object.
1068
- _.mixin = function(obj) {
1069
- each(_.functions(obj), function(name){
1070
- var func = _[name] = obj[name];
1071
- _.prototype[name] = function() {
1072
- var args = [this._wrapped];
1073
- push.apply(args, arguments);
1074
- return result.call(this, func.apply(_, args));
1075
- };
1076
- });
1246
+ return _.isFunction(value) ? object[property]() : value;
1077
1247
  };
1078
1248
 
1079
1249
  // Generate a unique integer id (unique within the entire client session).
@@ -1104,22 +1274,26 @@
1104
1274
  '\\': '\\',
1105
1275
  '\r': 'r',
1106
1276
  '\n': 'n',
1107
- '\t': 't',
1108
1277
  '\u2028': 'u2028',
1109
1278
  '\u2029': 'u2029'
1110
1279
  };
1111
1280
 
1112
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
1281
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
1282
+
1283
+ var escapeChar = function(match) {
1284
+ return '\\' + escapes[match];
1285
+ };
1113
1286
 
1114
1287
  // JavaScript micro-templating, similar to John Resig's implementation.
1115
1288
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
1116
1289
  // and correctly escapes quotes within interpolated code.
1117
- _.template = function(text, data, settings) {
1118
- var render;
1290
+ // NB: `oldSettings` only exists for backwards compatibility.
1291
+ _.template = function(text, settings, oldSettings) {
1292
+ if (!settings && oldSettings) settings = oldSettings;
1119
1293
  settings = _.defaults({}, settings, _.templateSettings);
1120
1294
 
1121
1295
  // Combine delimiters into one regular expression via alternation.
1122
- var matcher = new RegExp([
1296
+ var matcher = RegExp([
1123
1297
  (settings.escape || noMatch).source,
1124
1298
  (settings.interpolate || noMatch).source,
1125
1299
  (settings.evaluate || noMatch).source
@@ -1129,19 +1303,18 @@
1129
1303
  var index = 0;
1130
1304
  var source = "__p+='";
1131
1305
  text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
1132
- source += text.slice(index, offset)
1133
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
1306
+ source += text.slice(index, offset).replace(escaper, escapeChar);
1307
+ index = offset + match.length;
1134
1308
 
1135
1309
  if (escape) {
1136
1310
  source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
1137
- }
1138
- if (interpolate) {
1311
+ } else if (interpolate) {
1139
1312
  source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
1140
- }
1141
- if (evaluate) {
1313
+ } else if (evaluate) {
1142
1314
  source += "';\n" + evaluate + "\n__p+='";
1143
1315
  }
1144
- index = offset + match.length;
1316
+
1317
+ // Adobe VMs need the match returned to produce the correct offest.
1145
1318
  return match;
1146
1319
  });
1147
1320
  source += "';\n";
@@ -1151,29 +1324,31 @@
1151
1324
 
1152
1325
  source = "var __t,__p='',__j=Array.prototype.join," +
1153
1326
  "print=function(){__p+=__j.call(arguments,'');};\n" +
1154
- source + "return __p;\n";
1327
+ source + 'return __p;\n';
1155
1328
 
1156
1329
  try {
1157
- render = new Function(settings.variable || 'obj', '_', source);
1330
+ var render = new Function(settings.variable || 'obj', '_', source);
1158
1331
  } catch (e) {
1159
1332
  e.source = source;
1160
1333
  throw e;
1161
1334
  }
1162
1335
 
1163
- if (data) return render(data, _);
1164
1336
  var template = function(data) {
1165
1337
  return render.call(this, data, _);
1166
1338
  };
1167
1339
 
1168
- // Provide the compiled function source as a convenience for precompilation.
1169
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
1340
+ // Provide the compiled source as a convenience for precompilation.
1341
+ var argument = settings.variable || 'obj';
1342
+ template.source = 'function(' + argument + '){\n' + source + '}';
1170
1343
 
1171
1344
  return template;
1172
1345
  };
1173
1346
 
1174
- // Add a "chain" function, which will delegate to the wrapper.
1347
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
1175
1348
  _.chain = function(obj) {
1176
- return _(obj).chain();
1349
+ var instance = _(obj);
1350
+ instance._chain = true;
1351
+ return instance;
1177
1352
  };
1178
1353
 
1179
1354
  // OOP
@@ -1187,41 +1362,55 @@
1187
1362
  return this._chain ? _(obj).chain() : obj;
1188
1363
  };
1189
1364
 
1365
+ // Add your own custom functions to the Underscore object.
1366
+ _.mixin = function(obj) {
1367
+ _.each(_.functions(obj), function(name) {
1368
+ var func = _[name] = obj[name];
1369
+ _.prototype[name] = function() {
1370
+ var args = [this._wrapped];
1371
+ push.apply(args, arguments);
1372
+ return result.call(this, func.apply(_, args));
1373
+ };
1374
+ });
1375
+ };
1376
+
1190
1377
  // Add all of the Underscore functions to the wrapper object.
1191
1378
  _.mixin(_);
1192
1379
 
1193
1380
  // Add all mutator Array functions to the wrapper.
1194
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1381
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1195
1382
  var method = ArrayProto[name];
1196
1383
  _.prototype[name] = function() {
1197
1384
  var obj = this._wrapped;
1198
1385
  method.apply(obj, arguments);
1199
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
1386
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
1200
1387
  return result.call(this, obj);
1201
1388
  };
1202
1389
  });
1203
1390
 
1204
1391
  // Add all accessor Array functions to the wrapper.
1205
- each(['concat', 'join', 'slice'], function(name) {
1392
+ _.each(['concat', 'join', 'slice'], function(name) {
1206
1393
  var method = ArrayProto[name];
1207
1394
  _.prototype[name] = function() {
1208
1395
  return result.call(this, method.apply(this._wrapped, arguments));
1209
1396
  };
1210
1397
  });
1211
1398
 
1212
- _.extend(_.prototype, {
1213
-
1214
- // Start chaining a wrapped Underscore object.
1215
- chain: function() {
1216
- this._chain = true;
1217
- return this;
1218
- },
1219
-
1220
- // Extracts the result from a wrapped and chained object.
1221
- value: function() {
1222
- return this._wrapped;
1223
- }
1224
-
1225
- });
1226
-
1227
- }).call(this);
1399
+ // Extracts the result from a wrapped and chained object.
1400
+ _.prototype.value = function() {
1401
+ return this._wrapped;
1402
+ };
1403
+
1404
+ // AMD registration happens at the end for compatibility with AMD loaders
1405
+ // that may not enforce next-turn semantics on modules. Even though general
1406
+ // practice for AMD registration is to be anonymous, underscore registers
1407
+ // as a named module because, like jQuery, it is a base library that is
1408
+ // popular enough to be bundled in a third party lib, but not be part of
1409
+ // an AMD load request. Those cases could generate an error when an
1410
+ // anonymous define() is called outside of a loader request.
1411
+ if (typeof define === 'function' && define.amd) {
1412
+ define('underscore', [], function() {
1413
+ return _;
1414
+ });
1415
+ }
1416
+ }.call(this));