· 7 years ago · May 02, 2018, 02:40 PM
1Skip to content
2This repository
3Search
4Pull requests
5Issues
6Marketplace
7Explore
8 @ClintonTak
9Sign out
10924
1122,802 5,156 jashkenas/underscore
12 Code Issues 57 Pull requests 53 Projects 0 Wiki Insights
13underscore/underscore.js
14cbecaf0 14 days ago
15@jashkenas jashkenas Underscore.js 1.9.0
16@jashkenas @braddunbar @megawac @michaelficarra @jridgewell @gyeates @akre54 @captbaritone @ratbeard @ryantenney @davidchambers @mehdishojaei @jdalton @almost @octatone @mlanza @iamnoah @samuelclay @jamiebuilds @liuyl @AdamCraven @hackreactor-students @vincentwoo @lfac-pt @jrburke @caseywebdev
17
181689 lines (1497 sloc) 56.9 KB
19// Underscore.js 1.9.0
20// http://underscorejs.org
21// (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
22// Underscore may be freely distributed under the MIT license.
23
24(function() {
25
26 // Baseline setup
27 // --------------
28
29 // Establish the root object, `window` (`self`) in the browser, `global`
30 // on the server, or `this` in some virtual machines. We use `self`
31 // instead of `window` for `WebWorker` support.
32 var root = typeof self == 'object' && self.self === self && self ||
33 typeof global == 'object' && global.global === global && global ||
34 this ||
35 {};
36
37 // Save the previous value of the `_` variable.
38 var previousUnderscore = root._;
39
40 // Save bytes in the minified (but not gzipped) version:
41 var ArrayProto = Array.prototype, ObjProto = Object.prototype;
42 var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
43
44 // Create quick reference variables for speed access to core prototypes.
45 var push = ArrayProto.push,
46 slice = ArrayProto.slice,
47 toString = ObjProto.toString,
48 hasOwnProperty = ObjProto.hasOwnProperty;
49
50 // All **ECMAScript 5** native function implementations that we hope to use
51 // are declared here.
52 var nativeIsArray = Array.isArray,
53 nativeKeys = Object.keys,
54 nativeCreate = Object.create;
55
56 // Naked function reference for surrogate-prototype-swapping.
57 var Ctor = function(){};
58
59 // Create a safe reference to the Underscore object for use below.
60 var _ = function(obj) {
61 if (obj instanceof _) return obj;
62 if (!(this instanceof _)) return new _(obj);
63 this._wrapped = obj;
64 };
65
66 // Export the Underscore object for **Node.js**, with
67 // backwards-compatibility for their old module API. If we're in
68 // the browser, add `_` as a global object.
69 // (`nodeType` is checked to ensure that `module`
70 // and `exports` are not HTML elements.)
71 if (typeof exports != 'undefined' && !exports.nodeType) {
72 if (typeof module != 'undefined' && !module.nodeType && module.exports) {
73 exports = module.exports = _;
74 }
75 exports._ = _;
76 } else {
77 root._ = _;
78 }
79
80 // Current version.
81 _.VERSION = '1.9.0';
82
83 // Internal function that returns an efficient (for current engines) version
84 // of the passed-in callback, to be repeatedly applied in other Underscore
85 // functions.
86 var optimizeCb = function(func, context, argCount) {
87 if (context === void 0) return func;
88 switch (argCount == null ? 3 : argCount) {
89 case 1: return function(value) {
90 return func.call(context, value);
91 };
92 // The 2-argument case is omitted because we’re not using it.
93 case 3: return function(value, index, collection) {
94 return func.call(context, value, index, collection);
95 };
96 case 4: return function(accumulator, value, index, collection) {
97 return func.call(context, accumulator, value, index, collection);
98 };
99 }
100 return function() {
101 return func.apply(context, arguments);
102 };
103 };
104
105 var builtinIteratee;
106
107 // An internal function to generate callbacks that can be applied to each
108 // element in a collection, returning the desired result — either `identity`,
109 // an arbitrary callback, a property matcher, or a property accessor.
110 var cb = function(value, context, argCount) {
111 if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
112 if (value == null) return _.identity;
113 if (_.isFunction(value)) return optimizeCb(value, context, argCount);
114 if (_.isObject(value) && !_.isArray(value)) return _.matcher(value);
115 return _.property(value);
116 };
117
118 // External wrapper for our callback generator. Users may customize
119 // `_.iteratee` if they want additional predicate/iteratee shorthand styles.
120 // This abstraction hides the internal-only argCount argument.
121 _.iteratee = builtinIteratee = function(value, context) {
122 return cb(value, context, Infinity);
123 };
124
125 // Some functions take a variable number of arguments, or a few expected
126 // arguments at the beginning and then a variable number of values to operate
127 // on. This helper accumulates all remaining arguments past the function’s
128 // argument length (or an explicit `startIndex`), into an array that becomes
129 // the last argument. Similar to ES6’s "rest parameter".
130 var restArguments = function(func, startIndex) {
131 startIndex = startIndex == null ? func.length - 1 : +startIndex;
132 return function() {
133 var length = Math.max(arguments.length - startIndex, 0),
134 rest = Array(length),
135 index = 0;
136 for (; index < length; index++) {
137 rest[index] = arguments[index + startIndex];
138 }
139 switch (startIndex) {
140 case 0: return func.call(this, rest);
141 case 1: return func.call(this, arguments[0], rest);
142 case 2: return func.call(this, arguments[0], arguments[1], rest);
143 }
144 var args = Array(startIndex + 1);
145 for (index = 0; index < startIndex; index++) {
146 args[index] = arguments[index];
147 }
148 args[startIndex] = rest;
149 return func.apply(this, args);
150 };
151 };
152
153 // An internal function for creating a new object that inherits from another.
154 var baseCreate = function(prototype) {
155 if (!_.isObject(prototype)) return {};
156 if (nativeCreate) return nativeCreate(prototype);
157 Ctor.prototype = prototype;
158 var result = new Ctor;
159 Ctor.prototype = null;
160 return result;
161 };
162
163 var shallowProperty = function(key) {
164 return function(obj) {
165 return obj == null ? void 0 : obj[key];
166 };
167 };
168
169 var deepGet = function(obj, path) {
170 var length = path.length;
171 for (var i = 0; i < length; i++) {
172 if (obj == null) return void 0;
173 obj = obj[path[i]];
174 }
175 return length ? obj : void 0;
176 };
177
178 // Helper for collection methods to determine whether a collection
179 // should be iterated as an array or as an object.
180 // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
181 // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
182 var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
183 var getLength = shallowProperty('length');
184 var isArrayLike = function(collection) {
185 var length = getLength(collection);
186 return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
187 };
188
189 // Collection Functions
190 // --------------------
191
192 // The cornerstone, an `each` implementation, aka `forEach`.
193 // Handles raw objects in addition to array-likes. Treats all
194 // sparse array-likes as if they were dense.
195 _.each = _.forEach = function(obj, iteratee, context) {
196 iteratee = optimizeCb(iteratee, context);
197 var i, length;
198 if (isArrayLike(obj)) {
199 for (i = 0, length = obj.length; i < length; i++) {
200 iteratee(obj[i], i, obj);
201 }
202 } else {
203 var keys = _.keys(obj);
204 for (i = 0, length = keys.length; i < length; i++) {
205 iteratee(obj[keys[i]], keys[i], obj);
206 }
207 }
208 return obj;
209 };
210
211 // Return the results of applying the iteratee to each element.
212 _.map = _.collect = function(obj, iteratee, context) {
213 iteratee = cb(iteratee, context);
214 var keys = !isArrayLike(obj) && _.keys(obj),
215 length = (keys || obj).length,
216 results = Array(length);
217 for (var index = 0; index < length; index++) {
218 var currentKey = keys ? keys[index] : index;
219 results[index] = iteratee(obj[currentKey], currentKey, obj);
220 }
221 return results;
222 };
223
224 // Create a reducing function iterating left or right.
225 var createReduce = function(dir) {
226 // Wrap code that reassigns argument variables in a separate function than
227 // the one that accesses `arguments.length` to avoid a perf hit. (#1991)
228 var reducer = function(obj, iteratee, memo, initial) {
229 var keys = !isArrayLike(obj) && _.keys(obj),
230 length = (keys || obj).length,
231 index = dir > 0 ? 0 : length - 1;
232 if (!initial) {
233 memo = obj[keys ? keys[index] : index];
234 index += dir;
235 }
236 for (; index >= 0 && index < length; index += dir) {
237 var currentKey = keys ? keys[index] : index;
238 memo = iteratee(memo, obj[currentKey], currentKey, obj);
239 }
240 return memo;
241 };
242
243 return function(obj, iteratee, memo, context) {
244 var initial = arguments.length >= 3;
245 return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
246 };
247 };
248
249 // **Reduce** builds up a single result from a list of values, aka `inject`,
250 // or `foldl`.
251 _.reduce = _.foldl = _.inject = createReduce(1);
252
253 // The right-associative version of reduce, also known as `foldr`.
254 _.reduceRight = _.foldr = createReduce(-1);
255
256 // Return the first value which passes a truth test. Aliased as `detect`.
257 _.find = _.detect = function(obj, predicate, context) {
258 var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey;
259 var key = keyFinder(obj, predicate, context);
260 if (key !== void 0 && key !== -1) return obj[key];
261 };
262
263 // Return all the elements that pass a truth test.
264 // Aliased as `select`.
265 _.filter = _.select = function(obj, predicate, context) {
266 var results = [];
267 predicate = cb(predicate, context);
268 _.each(obj, function(value, index, list) {
269 if (predicate(value, index, list)) results.push(value);
270 });
271 return results;
272 };
273
274 // Return all the elements for which a truth test fails.
275 _.reject = function(obj, predicate, context) {
276 return _.filter(obj, _.negate(cb(predicate)), context);
277 };
278
279 // Determine whether all of the elements match a truth test.
280 // Aliased as `all`.
281 _.every = _.all = function(obj, predicate, context) {
282 predicate = cb(predicate, context);
283 var keys = !isArrayLike(obj) && _.keys(obj),
284 length = (keys || obj).length;
285 for (var index = 0; index < length; index++) {
286 var currentKey = keys ? keys[index] : index;
287 if (!predicate(obj[currentKey], currentKey, obj)) return false;
288 }
289 return true;
290 };
291
292 // Determine if at least one element in the object matches a truth test.
293 // Aliased as `any`.
294 _.some = _.any = function(obj, predicate, context) {
295 predicate = cb(predicate, context);
296 var keys = !isArrayLike(obj) && _.keys(obj),
297 length = (keys || obj).length;
298 for (var index = 0; index < length; index++) {
299 var currentKey = keys ? keys[index] : index;
300 if (predicate(obj[currentKey], currentKey, obj)) return true;
301 }
302 return false;
303 };
304
305 // Determine if the array or object contains a given item (using `===`).
306 // Aliased as `includes` and `include`.
307 _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
308 if (!isArrayLike(obj)) obj = _.values(obj);
309 if (typeof fromIndex != 'number' || guard) fromIndex = 0;
310 return _.indexOf(obj, item, fromIndex) >= 0;
311 };
312
313 // Invoke a method (with arguments) on every item in a collection.
314 _.invoke = restArguments(function(obj, path, args) {
315 var contextPath, func;
316 if (_.isFunction(path)) {
317 func = path;
318 } else if (_.isArray(path)) {
319 contextPath = path.slice(0, -1);
320 path = path[path.length - 1];
321 }
322 return _.map(obj, function(context) {
323 var method = func;
324 if (!method) {
325 if (contextPath && contextPath.length) {
326 context = deepGet(context, contextPath);
327 }
328 if (context == null) return void 0;
329 method = context[path];
330 }
331 return method == null ? method : method.apply(context, args);
332 });
333 });
334
335 // Convenience version of a common use case of `map`: fetching a property.
336 _.pluck = function(obj, key) {
337 return _.map(obj, _.property(key));
338 };
339
340 // Convenience version of a common use case of `filter`: selecting only objects
341 // containing specific `key:value` pairs.
342 _.where = function(obj, attrs) {
343 return _.filter(obj, _.matcher(attrs));
344 };
345
346 // Convenience version of a common use case of `find`: getting the first object
347 // containing specific `key:value` pairs.
348 _.findWhere = function(obj, attrs) {
349 return _.find(obj, _.matcher(attrs));
350 };
351
352 // Return the maximum element (or element-based computation).
353 _.max = function(obj, iteratee, context) {
354 var result = -Infinity, lastComputed = -Infinity,
355 value, computed;
356 if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
357 obj = isArrayLike(obj) ? obj : _.values(obj);
358 for (var i = 0, length = obj.length; i < length; i++) {
359 value = obj[i];
360 if (value != null && value > result) {
361 result = value;
362 }
363 }
364 } else {
365 iteratee = cb(iteratee, context);
366 _.each(obj, function(v, index, list) {
367 computed = iteratee(v, index, list);
368 if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
369 result = v;
370 lastComputed = computed;
371 }
372 });
373 }
374 return result;
375 };
376
377 // Return the minimum element (or element-based computation).
378 _.min = function(obj, iteratee, context) {
379 var result = Infinity, lastComputed = Infinity,
380 value, computed;
381 if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
382 obj = isArrayLike(obj) ? obj : _.values(obj);
383 for (var i = 0, length = obj.length; i < length; i++) {
384 value = obj[i];
385 if (value != null && value < result) {
386 result = value;
387 }
388 }
389 } else {
390 iteratee = cb(iteratee, context);
391 _.each(obj, function(v, index, list) {
392 computed = iteratee(v, index, list);
393 if (computed < lastComputed || computed === Infinity && result === Infinity) {
394 result = v;
395 lastComputed = computed;
396 }
397 });
398 }
399 return result;
400 };
401
402 // Shuffle a collection.
403 _.shuffle = function(obj) {
404 return _.sample(obj, Infinity);
405 };
406
407 // Sample **n** random values from a collection using the modern version of the
408 // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
409 // If **n** is not specified, returns a single random element.
410 // The internal `guard` argument allows it to work with `map`.
411 _.sample = function(obj, n, guard) {
412 if (n == null || guard) {
413 if (!isArrayLike(obj)) obj = _.values(obj);
414 return obj[_.random(obj.length - 1)];
415 }
416 var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj);
417 var length = getLength(sample);
418 n = Math.max(Math.min(n, length), 0);
419 var last = length - 1;
420 for (var index = 0; index < n; index++) {
421 var rand = _.random(index, last);
422 var temp = sample[index];
423 sample[index] = sample[rand];
424 sample[rand] = temp;
425 }
426 return sample.slice(0, n);
427 };
428
429 // Sort the object's values by a criterion produced by an iteratee.
430 _.sortBy = function(obj, iteratee, context) {
431 var index = 0;
432 iteratee = cb(iteratee, context);
433 return _.pluck(_.map(obj, function(value, key, list) {
434 return {
435 value: value,
436 index: index++,
437 criteria: iteratee(value, key, list)
438 };
439 }).sort(function(left, right) {
440 var a = left.criteria;
441 var b = right.criteria;
442 if (a !== b) {
443 if (a > b || a === void 0) return 1;
444 if (a < b || b === void 0) return -1;
445 }
446 return left.index - right.index;
447 }), 'value');
448 };
449
450 // An internal function used for aggregate "group by" operations.
451 var group = function(behavior, partition) {
452 return function(obj, iteratee, context) {
453 var result = partition ? [[], []] : {};
454 iteratee = cb(iteratee, context);
455 _.each(obj, function(value, index) {
456 var key = iteratee(value, index, obj);
457 behavior(result, value, key);
458 });
459 return result;
460 };
461 };
462
463 // Groups the object's values by a criterion. Pass either a string attribute
464 // to group by, or a function that returns the criterion.
465 _.groupBy = group(function(result, value, key) {
466 if (_.has(result, key)) result[key].push(value); else result[key] = [value];
467 });
468
469 // Indexes the object's values by a criterion, similar to `groupBy`, but for
470 // when you know that your index values will be unique.
471 _.indexBy = group(function(result, value, key) {
472 result[key] = value;
473 });
474
475 // Counts instances of an object that group by a certain criterion. Pass
476 // either a string attribute to count by, or a function that returns the
477 // criterion.
478 _.countBy = group(function(result, value, key) {
479 if (_.has(result, key)) result[key]++; else result[key] = 1;
480 });
481
482 var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;
483 // Safely create a real, live array from anything iterable.
484 _.toArray = function(obj) {
485 if (!obj) return [];
486 if (_.isArray(obj)) return slice.call(obj);
487 if (_.isString(obj)) {
488 // Keep surrogate pair characters together
489 return obj.match(reStrSymbol);
490 }
491 if (isArrayLike(obj)) return _.map(obj, _.identity);
492 return _.values(obj);
493 };
494
495 // Return the number of elements in an object.
496 _.size = function(obj) {
497 if (obj == null) return 0;
498 return isArrayLike(obj) ? obj.length : _.keys(obj).length;
499 };
500
501 // Split a collection into two arrays: one whose elements all satisfy the given
502 // predicate, and one whose elements all do not satisfy the predicate.
503 _.partition = group(function(result, value, pass) {
504 result[pass ? 0 : 1].push(value);
505 }, true);
506
507 // Array Functions
508 // ---------------
509
510 // Get the first element of an array. Passing **n** will return the first N
511 // values in the array. Aliased as `head` and `take`. The **guard** check
512 // allows it to work with `_.map`.
513 _.first = _.head = _.take = function(array, n, guard) {
514 if (array == null || array.length < 1) return void 0;
515 if (n == null || guard) return array[0];
516 return _.initial(array, array.length - n);
517 };
518
519 // Returns everything but the last entry of the array. Especially useful on
520 // the arguments object. Passing **n** will return all the values in
521 // the array, excluding the last N.
522 _.initial = function(array, n, guard) {
523 return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
524 };
525
526 // Get the last element of an array. Passing **n** will return the last N
527 // values in the array.
528 _.last = function(array, n, guard) {
529 if (array == null || array.length < 1) return void 0;
530 if (n == null || guard) return array[array.length - 1];
531 return _.rest(array, Math.max(0, array.length - n));
532 };
533
534 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
535 // Especially useful on the arguments object. Passing an **n** will return
536 // the rest N values in the array.
537 _.rest = _.tail = _.drop = function(array, n, guard) {
538 return slice.call(array, n == null || guard ? 1 : n);
539 };
540
541 // Trim out all falsy values from an array.
542 _.compact = function(array) {
543 return _.filter(array, Boolean);
544 };
545
546 // Internal implementation of a recursive `flatten` function.
547 var flatten = function(input, shallow, strict, output) {
548 output = output || [];
549 var idx = output.length;
550 for (var i = 0, length = getLength(input); i < length; i++) {
551 var value = input[i];
552 if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
553 // Flatten current level of array or arguments object.
554 if (shallow) {
555 var j = 0, len = value.length;
556 while (j < len) output[idx++] = value[j++];
557 } else {
558 flatten(value, shallow, strict, output);
559 idx = output.length;
560 }
561 } else if (!strict) {
562 output[idx++] = value;
563 }
564 }
565 return output;
566 };
567
568 // Flatten out an array, either recursively (by default), or just one level.
569 _.flatten = function(array, shallow) {
570 return flatten(array, shallow, false);
571 };
572
573 // Return a version of the array that does not contain the specified value(s).
574 _.without = restArguments(function(array, otherArrays) {
575 return _.difference(array, otherArrays);
576 });
577
578 // Produce a duplicate-free version of the array. If the array has already
579 // been sorted, you have the option of using a faster algorithm.
580 // The faster algorithm will not work with an iteratee if the iteratee
581 // is not a one-to-one function, so providing an iteratee will disable
582 // the faster algorithm.
583 // Aliased as `unique`.
584 _.uniq = _.unique = function(array, isSorted, iteratee, context) {
585 if (!_.isBoolean(isSorted)) {
586 context = iteratee;
587 iteratee = isSorted;
588 isSorted = false;
589 }
590 if (iteratee != null) iteratee = cb(iteratee, context);
591 var result = [];
592 var seen = [];
593 for (var i = 0, length = getLength(array); i < length; i++) {
594 var value = array[i],
595 computed = iteratee ? iteratee(value, i, array) : value;
596 if (isSorted && !iteratee) {
597 if (!i || seen !== computed) result.push(value);
598 seen = computed;
599 } else if (iteratee) {
600 if (!_.contains(seen, computed)) {
601 seen.push(computed);
602 result.push(value);
603 }
604 } else if (!_.contains(result, value)) {
605 result.push(value);
606 }
607 }
608 return result;
609 };
610
611 // Produce an array that contains the union: each distinct element from all of
612 // the passed-in arrays.
613 _.union = restArguments(function(arrays) {
614 return _.uniq(flatten(arrays, true, true));
615 });
616
617 // Produce an array that contains every item shared between all the
618 // passed-in arrays.
619 _.intersection = function(array) {
620 var result = [];
621 var argsLength = arguments.length;
622 for (var i = 0, length = getLength(array); i < length; i++) {
623 var item = array[i];
624 if (_.contains(result, item)) continue;
625 var j;
626 for (j = 1; j < argsLength; j++) {
627 if (!_.contains(arguments[j], item)) break;
628 }
629 if (j === argsLength) result.push(item);
630 }
631 return result;
632 };
633
634 // Take the difference between one array and a number of other arrays.
635 // Only the elements present in just the first array will remain.
636 _.difference = restArguments(function(array, rest) {
637 rest = flatten(rest, true, true);
638 return _.filter(array, function(value){
639 return !_.contains(rest, value);
640 });
641 });
642
643 // Complement of _.zip. Unzip accepts an array of arrays and groups
644 // each array's elements on shared indices.
645 _.unzip = function(array) {
646 var length = array && _.max(array, getLength).length || 0;
647 var result = Array(length);
648
649 for (var index = 0; index < length; index++) {
650 result[index] = _.pluck(array, index);
651 }
652 return result;
653 };
654
655 // Zip together multiple lists into a single array -- elements that share
656 // an index go together.
657 _.zip = restArguments(_.unzip);
658
659 // Converts lists into objects. Pass either a single array of `[key, value]`
660 // pairs, or two parallel arrays of the same length -- one of keys, and one of
661 // the corresponding values. Passing by pairs is the reverse of _.pairs.
662 _.object = function(list, values) {
663 var result = {};
664 for (var i = 0, length = getLength(list); i < length; i++) {
665 if (values) {
666 result[list[i]] = values[i];
667 } else {
668 result[list[i][0]] = list[i][1];
669 }
670 }
671 return result;
672 };
673
674 // Generator function to create the findIndex and findLastIndex functions.
675 var createPredicateIndexFinder = function(dir) {
676 return function(array, predicate, context) {
677 predicate = cb(predicate, context);
678 var length = getLength(array);
679 var index = dir > 0 ? 0 : length - 1;
680 for (; index >= 0 && index < length; index += dir) {
681 if (predicate(array[index], index, array)) return index;
682 }
683 return -1;
684 };
685 };
686
687 // Returns the first index on an array-like that passes a predicate test.
688 _.findIndex = createPredicateIndexFinder(1);
689 _.findLastIndex = createPredicateIndexFinder(-1);
690
691 // Use a comparator function to figure out the smallest index at which
692 // an object should be inserted so as to maintain order. Uses binary search.
693 _.sortedIndex = function(array, obj, iteratee, context) {
694 iteratee = cb(iteratee, context, 1);
695 var value = iteratee(obj);
696 var low = 0, high = getLength(array);
697 while (low < high) {
698 var mid = Math.floor((low + high) / 2);
699 if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
700 }
701 return low;
702 };
703
704 // Generator function to create the indexOf and lastIndexOf functions.
705 var createIndexFinder = function(dir, predicateFind, sortedIndex) {
706 return function(array, item, idx) {
707 var i = 0, length = getLength(array);
708 if (typeof idx == 'number') {
709 if (dir > 0) {
710 i = idx >= 0 ? idx : Math.max(idx + length, i);
711 } else {
712 length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
713 }
714 } else if (sortedIndex && idx && length) {
715 idx = sortedIndex(array, item);
716 return array[idx] === item ? idx : -1;
717 }
718 if (item !== item) {
719 idx = predicateFind(slice.call(array, i, length), _.isNaN);
720 return idx >= 0 ? idx + i : -1;
721 }
722 for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
723 if (array[idx] === item) return idx;
724 }
725 return -1;
726 };
727 };
728
729 // Return the position of the first occurrence of an item in an array,
730 // or -1 if the item is not included in the array.
731 // If the array is large and already in sort order, pass `true`
732 // for **isSorted** to use binary search.
733 _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
734 _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
735
736 // Generate an integer Array containing an arithmetic progression. A port of
737 // the native Python `range()` function. See
738 // [the Python documentation](http://docs.python.org/library/functions.html#range).
739 _.range = function(start, stop, step) {
740 if (stop == null) {
741 stop = start || 0;
742 start = 0;
743 }
744 if (!step) {
745 step = stop < start ? -1 : 1;
746 }
747
748 var length = Math.max(Math.ceil((stop - start) / step), 0);
749 var range = Array(length);
750
751 for (var idx = 0; idx < length; idx++, start += step) {
752 range[idx] = start;
753 }
754
755 return range;
756 };
757
758 // Chunk a single array into multiple arrays, each containing `count` or fewer
759 // items.
760 _.chunk = function(array, count) {
761 if (count == null || count < 1) return [];
762 var result = [];
763 var i = 0, length = array.length;
764 while (i < length) {
765 result.push(slice.call(array, i, i += count));
766 }
767 return result;
768 };
769
770 // Function (ahem) Functions
771 // ------------------
772
773 // Determines whether to execute a function as a constructor
774 // or a normal function with the provided arguments.
775 var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
776 if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
777 var self = baseCreate(sourceFunc.prototype);
778 var result = sourceFunc.apply(self, args);
779 if (_.isObject(result)) return result;
780 return self;
781 };
782
783 // Create a function bound to a given object (assigning `this`, and arguments,
784 // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
785 // available.
786 _.bind = restArguments(function(func, context, args) {
787 if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
788 var bound = restArguments(function(callArgs) {
789 return executeBound(func, bound, context, this, args.concat(callArgs));
790 });
791 return bound;
792 });
793
794 // Partially apply a function by creating a version that has had some of its
795 // arguments pre-filled, without changing its dynamic `this` context. _ acts
796 // as a placeholder by default, allowing any combination of arguments to be
797 // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
798 _.partial = restArguments(function(func, boundArgs) {
799 var placeholder = _.partial.placeholder;
800 var bound = function() {
801 var position = 0, length = boundArgs.length;
802 var args = Array(length);
803 for (var i = 0; i < length; i++) {
804 args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
805 }
806 while (position < arguments.length) args.push(arguments[position++]);
807 return executeBound(func, bound, this, this, args);
808 };
809 return bound;
810 });
811
812 _.partial.placeholder = _;
813
814 // Bind a number of an object's methods to that object. Remaining arguments
815 // are the method names to be bound. Useful for ensuring that all callbacks
816 // defined on an object belong to it.
817 _.bindAll = restArguments(function(obj, keys) {
818 keys = flatten(keys, false, false);
819 var index = keys.length;
820 if (index < 1) throw new Error('bindAll must be passed function names');
821 while (index--) {
822 var key = keys[index];
823 obj[key] = _.bind(obj[key], obj);
824 }
825 });
826
827 // Memoize an expensive function by storing its results.
828 _.memoize = function(func, hasher) {
829 var memoize = function(key) {
830 var cache = memoize.cache;
831 var address = '' + (hasher ? hasher.apply(this, arguments) : key);
832 if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
833 return cache[address];
834 };
835 memoize.cache = {};
836 return memoize;
837 };
838
839 // Delays a function for the given number of milliseconds, and then calls
840 // it with the arguments supplied.
841 _.delay = restArguments(function(func, wait, args) {
842 return setTimeout(function() {
843 return func.apply(null, args);
844 }, wait);
845 });
846
847 // Defers a function, scheduling it to run after the current call stack has
848 // cleared.
849 _.defer = _.partial(_.delay, _, 1);
850
851 // Returns a function, that, when invoked, will only be triggered at most once
852 // during a given window of time. Normally, the throttled function will run
853 // as much as it can, without ever going more than once per `wait` duration;
854 // but if you'd like to disable the execution on the leading edge, pass
855 // `{leading: false}`. To disable execution on the trailing edge, ditto.
856 _.throttle = function(func, wait, options) {
857 var timeout, context, args, result;
858 var previous = 0;
859 if (!options) options = {};
860
861 var later = function() {
862 previous = options.leading === false ? 0 : _.now();
863 timeout = null;
864 result = func.apply(context, args);
865 if (!timeout) context = args = null;
866 };
867
868 var throttled = function() {
869 var now = _.now();
870 if (!previous && options.leading === false) previous = now;
871 var remaining = wait - (now - previous);
872 context = this;
873 args = arguments;
874 if (remaining <= 0 || remaining > wait) {
875 if (timeout) {
876 clearTimeout(timeout);
877 timeout = null;
878 }
879 previous = now;
880 result = func.apply(context, args);
881 if (!timeout) context = args = null;
882 } else if (!timeout && options.trailing !== false) {
883 timeout = setTimeout(later, remaining);
884 }
885 return result;
886 };
887
888 throttled.cancel = function() {
889 clearTimeout(timeout);
890 previous = 0;
891 timeout = context = args = null;
892 };
893
894 return throttled;
895 };
896
897 // Returns a function, that, as long as it continues to be invoked, will not
898 // be triggered. The function will be called after it stops being called for
899 // N milliseconds. If `immediate` is passed, trigger the function on the
900 // leading edge, instead of the trailing.
901 _.debounce = function(func, wait, immediate) {
902 var timeout, result;
903
904 var later = function(context, args) {
905 timeout = null;
906 if (args) result = func.apply(context, args);
907 };
908
909 var debounced = restArguments(function(args) {
910 if (timeout) clearTimeout(timeout);
911 if (immediate) {
912 var callNow = !timeout;
913 timeout = setTimeout(later, wait);
914 if (callNow) result = func.apply(this, args);
915 } else {
916 timeout = _.delay(later, wait, this, args);
917 }
918
919 return result;
920 });
921
922 debounced.cancel = function() {
923 clearTimeout(timeout);
924 timeout = null;
925 };
926
927 return debounced;
928 };
929
930 // Returns the first function passed as an argument to the second,
931 // allowing you to adjust arguments, run code before and after, and
932 // conditionally execute the original function.
933 _.wrap = function(func, wrapper) {
934 return _.partial(wrapper, func);
935 };
936
937 // Returns a negated version of the passed-in predicate.
938 _.negate = function(predicate) {
939 return function() {
940 return !predicate.apply(this, arguments);
941 };
942 };
943
944 // Returns a function that is the composition of a list of functions, each
945 // consuming the return value of the function that follows.
946 _.compose = function() {
947 var args = arguments;
948 var start = args.length - 1;
949 return function() {
950 var i = start;
951 var result = args[start].apply(this, arguments);
952 while (i--) result = args[i].call(this, result);
953 return result;
954 };
955 };
956
957 // Returns a function that will only be executed on and after the Nth call.
958 _.after = function(times, func) {
959 return function() {
960 if (--times < 1) {
961 return func.apply(this, arguments);
962 }
963 };
964 };
965
966 // Returns a function that will only be executed up to (but not including) the Nth call.
967 _.before = function(times, func) {
968 var memo;
969 return function() {
970 if (--times > 0) {
971 memo = func.apply(this, arguments);
972 }
973 if (times <= 1) func = null;
974 return memo;
975 };
976 };
977
978 // Returns a function that will be executed at most one time, no matter how
979 // often you call it. Useful for lazy initialization.
980 _.once = _.partial(_.before, 2);
981
982 _.restArguments = restArguments;
983
984 // Object Functions
985 // ----------------
986
987 // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
988 var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
989 var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
990 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
991
992 var collectNonEnumProps = function(obj, keys) {
993 var nonEnumIdx = nonEnumerableProps.length;
994 var constructor = obj.constructor;
995 var proto = _.isFunction(constructor) && constructor.prototype || ObjProto;
996
997 // Constructor is a special case.
998 var prop = 'constructor';
999 if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
1000
1001 while (nonEnumIdx--) {
1002 prop = nonEnumerableProps[nonEnumIdx];
1003 if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
1004 keys.push(prop);
1005 }
1006 }
1007 };
1008
1009 // Retrieve the names of an object's own properties.
1010 // Delegates to **ECMAScript 5**'s native `Object.keys`.
1011 _.keys = function(obj) {
1012 if (!_.isObject(obj)) return [];
1013 if (nativeKeys) return nativeKeys(obj);
1014 var keys = [];
1015 for (var key in obj) if (_.has(obj, key)) keys.push(key);
1016 // Ahem, IE < 9.
1017 if (hasEnumBug) collectNonEnumProps(obj, keys);
1018 return keys;
1019 };
1020
1021 // Retrieve all the property names of an object.
1022 _.allKeys = function(obj) {
1023 if (!_.isObject(obj)) return [];
1024 var keys = [];
1025 for (var key in obj) keys.push(key);
1026 // Ahem, IE < 9.
1027 if (hasEnumBug) collectNonEnumProps(obj, keys);
1028 return keys;
1029 };
1030
1031 // Retrieve the values of an object's properties.
1032 _.values = function(obj) {
1033 var keys = _.keys(obj);
1034 var length = keys.length;
1035 var values = Array(length);
1036 for (var i = 0; i < length; i++) {
1037 values[i] = obj[keys[i]];
1038 }
1039 return values;
1040 };
1041
1042 // Returns the results of applying the iteratee to each element of the object.
1043 // In contrast to _.map it returns an object.
1044 _.mapObject = function(obj, iteratee, context) {
1045 iteratee = cb(iteratee, context);
1046 var keys = _.keys(obj),
1047 length = keys.length,
1048 results = {};
1049 for (var index = 0; index < length; index++) {
1050 var currentKey = keys[index];
1051 results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
1052 }
1053 return results;
1054 };
1055
1056 // Convert an object into a list of `[key, value]` pairs.
1057 // The opposite of _.object.
1058 _.pairs = function(obj) {
1059 var keys = _.keys(obj);
1060 var length = keys.length;
1061 var pairs = Array(length);
1062 for (var i = 0; i < length; i++) {
1063 pairs[i] = [keys[i], obj[keys[i]]];
1064 }
1065 return pairs;
1066 };
1067
1068 // Invert the keys and values of an object. The values must be serializable.
1069 _.invert = function(obj) {
1070 var result = {};
1071 var keys = _.keys(obj);
1072 for (var i = 0, length = keys.length; i < length; i++) {
1073 result[obj[keys[i]]] = keys[i];
1074 }
1075 return result;
1076 };
1077
1078 // Return a sorted list of the function names available on the object.
1079 // Aliased as `methods`.
1080 _.functions = _.methods = function(obj) {
1081 var names = [];
1082 for (var key in obj) {
1083 if (_.isFunction(obj[key])) names.push(key);
1084 }
1085 return names.sort();
1086 };
1087
1088 // An internal function for creating assigner functions.
1089 var createAssigner = function(keysFunc, defaults) {
1090 return function(obj) {
1091 var length = arguments.length;
1092 if (defaults) obj = Object(obj);
1093 if (length < 2 || obj == null) return obj;
1094 for (var index = 1; index < length; index++) {
1095 var source = arguments[index],
1096 keys = keysFunc(source),
1097 l = keys.length;
1098 for (var i = 0; i < l; i++) {
1099 var key = keys[i];
1100 if (!defaults || obj[key] === void 0) obj[key] = source[key];
1101 }
1102 }
1103 return obj;
1104 };
1105 };
1106
1107 // Extend a given object with all the properties in passed-in object(s).
1108 _.extend = createAssigner(_.allKeys);
1109
1110 // Assigns a given object with all the own properties in the passed-in object(s).
1111 // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
1112 _.extendOwn = _.assign = createAssigner(_.keys);
1113
1114 // Returns the first key on an object that passes a predicate test.
1115 _.findKey = function(obj, predicate, context) {
1116 predicate = cb(predicate, context);
1117 var keys = _.keys(obj), key;
1118 for (var i = 0, length = keys.length; i < length; i++) {
1119 key = keys[i];
1120 if (predicate(obj[key], key, obj)) return key;
1121 }
1122 };
1123
1124 // Internal pick helper function to determine if `obj` has key `key`.
1125 var keyInObj = function(value, key, obj) {
1126 return key in obj;
1127 };
1128
1129 // Return a copy of the object only containing the whitelisted properties.
1130 _.pick = restArguments(function(obj, keys) {
1131 var result = {}, iteratee = keys[0];
1132 if (obj == null) return result;
1133 if (_.isFunction(iteratee)) {
1134 if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
1135 keys = _.allKeys(obj);
1136 } else {
1137 iteratee = keyInObj;
1138 keys = flatten(keys, false, false);
1139 obj = Object(obj);
1140 }
1141 for (var i = 0, length = keys.length; i < length; i++) {
1142 var key = keys[i];
1143 var value = obj[key];
1144 if (iteratee(value, key, obj)) result[key] = value;
1145 }
1146 return result;
1147 });
1148
1149 // Return a copy of the object without the blacklisted properties.
1150 _.omit = restArguments(function(obj, keys) {
1151 var iteratee = keys[0], context;
1152 if (_.isFunction(iteratee)) {
1153 iteratee = _.negate(iteratee);
1154 if (keys.length > 1) context = keys[1];
1155 } else {
1156 keys = _.map(flatten(keys, false, false), String);
1157 iteratee = function(value, key) {
1158 return !_.contains(keys, key);
1159 };
1160 }
1161 return _.pick(obj, iteratee, context);
1162 });
1163
1164 // Fill in a given object with default properties.
1165 _.defaults = createAssigner(_.allKeys, true);
1166
1167 // Creates an object that inherits from the given prototype object.
1168 // If additional properties are provided then they will be added to the
1169 // created object.
1170 _.create = function(prototype, props) {
1171 var result = baseCreate(prototype);
1172 if (props) _.extendOwn(result, props);
1173 return result;
1174 };
1175
1176 // Create a (shallow-cloned) duplicate of an object.
1177 _.clone = function(obj) {
1178 if (!_.isObject(obj)) return obj;
1179 return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
1180 };
1181
1182 // Invokes interceptor with the obj, and then returns obj.
1183 // The primary purpose of this method is to "tap into" a method chain, in
1184 // order to perform operations on intermediate results within the chain.
1185 _.tap = function(obj, interceptor) {
1186 interceptor(obj);
1187 return obj;
1188 };
1189
1190 // Returns whether an object has a given set of `key:value` pairs.
1191 _.isMatch = function(object, attrs) {
1192 var keys = _.keys(attrs), length = keys.length;
1193 if (object == null) return !length;
1194 var obj = Object(object);
1195 for (var i = 0; i < length; i++) {
1196 var key = keys[i];
1197 if (attrs[key] !== obj[key] || !(key in obj)) return false;
1198 }
1199 return true;
1200 };
1201
1202
1203 // Internal recursive comparison function for `isEqual`.
1204 var eq, deepEq;
1205 eq = function(a, b, aStack, bStack) {
1206 // Identical objects are equal. `0 === -0`, but they aren't identical.
1207 // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1208 if (a === b) return a !== 0 || 1 / a === 1 / b;
1209 // `null` or `undefined` only equal to itself (strict comparison).
1210 if (a == null || b == null) return false;
1211 // `NaN`s are equivalent, but non-reflexive.
1212 if (a !== a) return b !== b;
1213 // Exhaust primitive checks
1214 var type = typeof a;
1215 if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
1216 return deepEq(a, b, aStack, bStack);
1217 };
1218
1219 // Internal recursive comparison function for `isEqual`.
1220 deepEq = function(a, b, aStack, bStack) {
1221 // Unwrap any wrapped objects.
1222 if (a instanceof _) a = a._wrapped;
1223 if (b instanceof _) b = b._wrapped;
1224 // Compare `[[Class]]` names.
1225 var className = toString.call(a);
1226 if (className !== toString.call(b)) return false;
1227 switch (className) {
1228 // Strings, numbers, regular expressions, dates, and booleans are compared by value.
1229 case '[object RegExp]':
1230 // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
1231 case '[object String]':
1232 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1233 // equivalent to `new String("5")`.
1234 return '' + a === '' + b;
1235 case '[object Number]':
1236 // `NaN`s are equivalent, but non-reflexive.
1237 // Object(NaN) is equivalent to NaN.
1238 if (+a !== +a) return +b !== +b;
1239 // An `egal` comparison is performed for other numeric values.
1240 return +a === 0 ? 1 / +a === 1 / b : +a === +b;
1241 case '[object Date]':
1242 case '[object Boolean]':
1243 // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1244 // millisecond representations. Note that invalid dates with millisecond representations
1245 // of `NaN` are not equivalent.
1246 return +a === +b;
1247 case '[object Symbol]':
1248 return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
1249 }
1250
1251 var areArrays = className === '[object Array]';
1252 if (!areArrays) {
1253 if (typeof a != 'object' || typeof b != 'object') return false;
1254
1255 // Objects with different constructors are not equivalent, but `Object`s or `Array`s
1256 // from different frames are.
1257 var aCtor = a.constructor, bCtor = b.constructor;
1258 if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
1259 _.isFunction(bCtor) && bCtor instanceof bCtor)
1260 && ('constructor' in a && 'constructor' in b)) {
1261 return false;
1262 }
1263 }
1264 // Assume equality for cyclic structures. The algorithm for detecting cyclic
1265 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1266
1267 // Initializing stack of traversed objects.
1268 // It's done here since we only need them for objects and arrays comparison.
1269 aStack = aStack || [];
1270 bStack = bStack || [];
1271 var length = aStack.length;
1272 while (length--) {
1273 // Linear search. Performance is inversely proportional to the number of
1274 // unique nested structures.
1275 if (aStack[length] === a) return bStack[length] === b;
1276 }
1277
1278 // Add the first object to the stack of traversed objects.
1279 aStack.push(a);
1280 bStack.push(b);
1281
1282 // Recursively compare objects and arrays.
1283 if (areArrays) {
1284 // Compare array lengths to determine if a deep comparison is necessary.
1285 length = a.length;
1286 if (length !== b.length) return false;
1287 // Deep compare the contents, ignoring non-numeric properties.
1288 while (length--) {
1289 if (!eq(a[length], b[length], aStack, bStack)) return false;
1290 }
1291 } else {
1292 // Deep compare objects.
1293 var keys = _.keys(a), key;
1294 length = keys.length;
1295 // Ensure that both objects contain the same number of properties before comparing deep equality.
1296 if (_.keys(b).length !== length) return false;
1297 while (length--) {
1298 // Deep compare each member
1299 key = keys[length];
1300 if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
1301 }
1302 }
1303 // Remove the first object from the stack of traversed objects.
1304 aStack.pop();
1305 bStack.pop();
1306 return true;
1307 };
1308
1309 // Perform a deep comparison to check if two objects are equal.
1310 _.isEqual = function(a, b) {
1311 return eq(a, b);
1312 };
1313
1314 // Is a given array, string, or object empty?
1315 // An "empty" object has no enumerable own-properties.
1316 _.isEmpty = function(obj) {
1317 if (obj == null) return true;
1318 if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
1319 return _.keys(obj).length === 0;
1320 };
1321
1322 // Is a given value a DOM element?
1323 _.isElement = function(obj) {
1324 return !!(obj && obj.nodeType === 1);
1325 };
1326
1327 // Is a given value an array?
1328 // Delegates to ECMA5's native Array.isArray
1329 _.isArray = nativeIsArray || function(obj) {
1330 return toString.call(obj) === '[object Array]';
1331 };
1332
1333 // Is a given variable an object?
1334 _.isObject = function(obj) {
1335 var type = typeof obj;
1336 return type === 'function' || type === 'object' && !!obj;
1337 };
1338
1339 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError, isMap, isWeakMap, isSet, isWeakSet.
1340 _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakMap', 'Set', 'WeakSet'], function(name) {
1341 _['is' + name] = function(obj) {
1342 return toString.call(obj) === '[object ' + name + ']';
1343 };
1344 });
1345
1346 // Define a fallback version of the method in browsers (ahem, IE < 9), where
1347 // there isn't any inspectable "Arguments" type.
1348 if (!_.isArguments(arguments)) {
1349 _.isArguments = function(obj) {
1350 return _.has(obj, 'callee');
1351 };
1352 }
1353
1354 // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
1355 // IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
1356 var nodelist = root.document && root.document.childNodes;
1357 if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
1358 _.isFunction = function(obj) {
1359 return typeof obj == 'function' || false;
1360 };
1361 }
1362
1363 // Is a given object a finite number?
1364 _.isFinite = function(obj) {
1365 return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj));
1366 };
1367
1368 // Is the given value `NaN`?
1369 _.isNaN = function(obj) {
1370 return _.isNumber(obj) && isNaN(obj);
1371 };
1372
1373 // Is a given value a boolean?
1374 _.isBoolean = function(obj) {
1375 return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
1376 };
1377
1378 // Is a given value equal to null?
1379 _.isNull = function(obj) {
1380 return obj === null;
1381 };
1382
1383 // Is a given variable undefined?
1384 _.isUndefined = function(obj) {
1385 return obj === void 0;
1386 };
1387
1388 // Shortcut function for checking if an object has a given property directly
1389 // on itself (in other words, not on a prototype).
1390 _.has = function(obj, path) {
1391 if (!_.isArray(path)) {
1392 return obj != null && hasOwnProperty.call(obj, path);
1393 }
1394 var length = path.length;
1395 for (var i = 0; i < length; i++) {
1396 var key = path[i];
1397 if (obj == null || !hasOwnProperty.call(obj, key)) {
1398 return false;
1399 }
1400 obj = obj[key];
1401 }
1402 return !!length;
1403 };
1404
1405 // Utility Functions
1406 // -----------------
1407
1408 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
1409 // previous owner. Returns a reference to the Underscore object.
1410 _.noConflict = function() {
1411 root._ = previousUnderscore;
1412 return this;
1413 };
1414
1415 // Keep the identity function around for default iteratees.
1416 _.identity = function(value) {
1417 return value;
1418 };
1419
1420 // Predicate-generating functions. Often useful outside of Underscore.
1421 _.constant = function(value) {
1422 return function() {
1423 return value;
1424 };
1425 };
1426
1427 _.noop = function(){};
1428
1429 // Creates a function that, when passed an object, will traverse that object’s
1430 // properties down the given `path`, specified as an array of keys or indexes.
1431 _.property = function(path) {
1432 if (!_.isArray(path)) {
1433 return shallowProperty(path);
1434 }
1435 return function(obj) {
1436 return deepGet(obj, path);
1437 };
1438 };
1439
1440 // Generates a function for a given object that returns a given property.
1441 _.propertyOf = function(obj) {
1442 if (obj == null) {
1443 return function(){};
1444 }
1445 return function(path) {
1446 return !_.isArray(path) ? obj[path] : deepGet(obj, path);
1447 };
1448 };
1449
1450 // Returns a predicate for checking whether an object has a given set of
1451 // `key:value` pairs.
1452 _.matcher = _.matches = function(attrs) {
1453 attrs = _.extendOwn({}, attrs);
1454 return function(obj) {
1455 return _.isMatch(obj, attrs);
1456 };
1457 };
1458
1459 // Run a function **n** times.
1460 _.times = function(n, iteratee, context) {
1461 var accum = Array(Math.max(0, n));
1462 iteratee = optimizeCb(iteratee, context, 1);
1463 for (var i = 0; i < n; i++) accum[i] = iteratee(i);
1464 return accum;
1465 };
1466
1467 // Return a random integer between min and max (inclusive).
1468 _.random = function(min, max) {
1469 if (max == null) {
1470 max = min;
1471 min = 0;
1472 }
1473 return min + Math.floor(Math.random() * (max - min + 1));
1474 };
1475
1476 // A (possibly faster) way to get the current timestamp as an integer.
1477 _.now = Date.now || function() {
1478 return new Date().getTime();
1479 };
1480
1481 // List of HTML entities for escaping.
1482 var escapeMap = {
1483 '&': '&',
1484 '<': '<',
1485 '>': '>',
1486 '"': '"',
1487 "'": ''',
1488 '`': '`'
1489 };
1490 var unescapeMap = _.invert(escapeMap);
1491
1492 // Functions for escaping and unescaping strings to/from HTML interpolation.
1493 var createEscaper = function(map) {
1494 var escaper = function(match) {
1495 return map[match];
1496 };
1497 // Regexes for identifying a key that needs to be escaped.
1498 var source = '(?:' + _.keys(map).join('|') + ')';
1499 var testRegexp = RegExp(source);
1500 var replaceRegexp = RegExp(source, 'g');
1501 return function(string) {
1502 string = string == null ? '' : '' + string;
1503 return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
1504 };
1505 };
1506 _.escape = createEscaper(escapeMap);
1507 _.unescape = createEscaper(unescapeMap);
1508
1509 // Traverses the children of `obj` along `path`. If a child is a function, it
1510 // is invoked with its parent as context. Returns the value of the final
1511 // child, or `fallback` if any child is undefined.
1512 _.result = function(obj, path, fallback) {
1513 if (!_.isArray(path)) path = [path];
1514 var length = path.length;
1515 if (!length) {
1516 return _.isFunction(fallback) ? fallback.call(obj) : fallback;
1517 }
1518 for (var i = 0; i < length; i++) {
1519 var prop = obj == null ? void 0 : obj[path[i]];
1520 if (prop === void 0) {
1521 prop = fallback;
1522 i = length; // Ensure we don't continue iterating.
1523 }
1524 obj = _.isFunction(prop) ? prop.call(obj) : prop;
1525 }
1526 return obj;
1527 };
1528
1529 // Generate a unique integer id (unique within the entire client session).
1530 // Useful for temporary DOM ids.
1531 var idCounter = 0;
1532 _.uniqueId = function(prefix) {
1533 var id = ++idCounter + '';
1534 return prefix ? prefix + id : id;
1535 };
1536
1537 // By default, Underscore uses ERB-style template delimiters, change the
1538 // following template settings to use alternative delimiters.
1539 _.templateSettings = {
1540 evaluate: /<%([\s\S]+?)%>/g,
1541 interpolate: /<%=([\s\S]+?)%>/g,
1542 escape: /<%-([\s\S]+?)%>/g
1543 };
1544
1545 // When customizing `templateSettings`, if you don't want to define an
1546 // interpolation, evaluation or escaping regex, we need one that is
1547 // guaranteed not to match.
1548 var noMatch = /(.)^/;
1549
1550 // Certain characters need to be escaped so that they can be put into a
1551 // string literal.
1552 var escapes = {
1553 "'": "'",
1554 '\\': '\\',
1555 '\r': 'r',
1556 '\n': 'n',
1557 '\u2028': 'u2028',
1558 '\u2029': 'u2029'
1559 };
1560
1561 var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
1562
1563 var escapeChar = function(match) {
1564 return '\\' + escapes[match];
1565 };
1566
1567 // JavaScript micro-templating, similar to John Resig's implementation.
1568 // Underscore templating handles arbitrary delimiters, preserves whitespace,
1569 // and correctly escapes quotes within interpolated code.
1570 // NB: `oldSettings` only exists for backwards compatibility.
1571 _.template = function(text, settings, oldSettings) {
1572 if (!settings && oldSettings) settings = oldSettings;
1573 settings = _.defaults({}, settings, _.templateSettings);
1574
1575 // Combine delimiters into one regular expression via alternation.
1576 var matcher = RegExp([
1577 (settings.escape || noMatch).source,
1578 (settings.interpolate || noMatch).source,
1579 (settings.evaluate || noMatch).source
1580 ].join('|') + '|$', 'g');
1581
1582 // Compile the template source, escaping string literals appropriately.
1583 var index = 0;
1584 var source = "__p+='";
1585 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
1586 source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
1587 index = offset + match.length;
1588
1589 if (escape) {
1590 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
1591 } else if (interpolate) {
1592 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
1593 } else if (evaluate) {
1594 source += "';\n" + evaluate + "\n__p+='";
1595 }
1596
1597 // Adobe VMs need the match returned to produce the correct offset.
1598 return match;
1599 });
1600 source += "';\n";
1601
1602 // If a variable is not specified, place data values in local scope.
1603 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
1604
1605 source = "var __t,__p='',__j=Array.prototype.join," +
1606 "print=function(){__p+=__j.call(arguments,'');};\n" +
1607 source + 'return __p;\n';
1608
1609 var render;
1610 try {
1611 render = new Function(settings.variable || 'obj', '_', source);
1612 } catch (e) {
1613 e.source = source;
1614 throw e;
1615 }
1616
1617 var template = function(data) {
1618 return render.call(this, data, _);
1619 };
1620
1621 // Provide the compiled source as a convenience for precompilation.
1622 var argument = settings.variable || 'obj';
1623 template.source = 'function(' + argument + '){\n' + source + '}';
1624
1625 return template;
1626 };
1627
1628 // Add a "chain" function. Start chaining a wrapped Underscore object.
1629 _.chain = function(obj) {
1630 var instance = _(obj);
1631 instance._chain = true;
1632 return instance;
1633 };
1634
1635 // OOP
1636 // ---------------
1637 // If Underscore is called as a function, it returns a wrapped object that
1638 // can be used OO-style. This wrapper holds altered versions of all the
1639 // underscore functions. Wrapped objects may be chained.
1640
1641 // Helper function to continue chaining intermediate results.
1642 var chainResult = function(instance, obj) {
1643 return instance._chain ? _(obj).chain() : obj;
1644 };
1645
1646 // Add your own custom functions to the Underscore object.
1647 _.mixin = function(obj) {
1648 _.each(_.functions(obj), function(name) {
1649 var func = _[name] = obj[name];
1650 _.prototype[name] = function() {
1651 var args = [this._wrapped];
1652 push.apply(args, arguments);
1653 return chainResult(this, func.apply(_, args));
1654 };
1655 });
1656 return _;
1657 };
1658
1659 // Add all of the Underscore functions to the wrapper object.
1660 _.mixin(_);
1661
1662 // Add all mutator Array functions to the wrapper.
1663 _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1664 var method = ArrayProto[name];
1665 _.prototype[name] = function() {
1666 var obj = this._wrapped;
1667 method.apply(obj, arguments);
1668 if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
1669 return chainResult(this, obj);
1670 };
1671 });
1672
1673 // Add all accessor Array functions to the wrapper.
1674 _.each(['concat', 'join', 'slice'], function(name) {
1675 var method = ArrayProto[name];
1676 _.prototype[name] = function() {
1677 return chainResult(this, method.apply(this._wrapped, arguments));
1678 };
1679 });
1680
1681 // Extracts the result from a wrapped and chained object.
1682 _.prototype.value = function() {
1683 return this._wrapped;
1684 };
1685
1686 // Provide unwrapping proxy for some methods used in engine operations
1687 // such as arithmetic and JSON stringification.
1688 _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
1689
1690 _.prototype.toString = function() {
1691 return String(this._wrapped);
1692 };
1693
1694 // AMD registration happens at the end for compatibility with AMD loaders
1695 // that may not enforce next-turn semantics on modules. Even though general
1696 // practice for AMD registration is to be anonymous, underscore registers
1697 // as a named module because, like jQuery, it is a base library that is
1698 // popular enough to be bundled in a third party lib, but not be part of
1699 // an AMD load request. Those cases could generate an error when an
1700 // anonymous define() is called outside of a loader request.
1701 if (typeof define == 'function' && define.amd) {
1702 define('underscore', [], function() {
1703 return _;
1704 });
1705 }
1706}());
1707© 2018 GitHub, Inc.
1708Terms
1709Privacy
1710Security
1711Status
1712Help
1713Contact GitHub
1714API
1715Training
1716Shop
1717Blog
1718About
1719Press h to open a hovercard with more details.