|
122 | 122 | return result; |
123 | 123 | }; |
124 | 124 |
|
| 125 | + var property = function(key) { |
| 126 | + return function(obj) { |
| 127 | + return obj == null ? void 0 : obj[key]; |
| 128 | + }; |
| 129 | + }; |
| 130 | + |
125 | 131 | // Helper for collection methods to determine whether a collection |
126 | 132 | // should be iterated as an array or as an object |
127 | 133 | // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength |
128 | 134 | // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 |
129 | | - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1, LENGTH = 'length'; |
| 135 | + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; |
| 136 | + var getLength = property('length'); |
130 | 137 | var isArrayLike = function(collection) { |
131 | | - var length = collection != null && collection[LENGTH]; |
| 138 | + var length = getLength(collection); |
132 | 139 | return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; |
133 | 140 | }; |
134 | 141 |
|
|
482 | 489 | // Internal implementation of a recursive `flatten` function. |
483 | 490 | var flatten = function(input, shallow, strict, startIndex) { |
484 | 491 | var output = [], idx = 0; |
485 | | - for (var i = startIndex || 0, length = input && input.length; i < length; i++) { |
| 492 | + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { |
486 | 493 | var value = input[i]; |
487 | 494 | if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { |
488 | 495 | //flatten current level of array or arguments object |
|
513 | 520 | // been sorted, you have the option of using a faster algorithm. |
514 | 521 | // Aliased as `unique`. |
515 | 522 | _.uniq = _.unique = function(array, isSorted, iteratee, context) { |
516 | | - if (array == null) return []; |
517 | 523 | if (!_.isBoolean(isSorted)) { |
518 | 524 | context = iteratee; |
519 | 525 | iteratee = isSorted; |
|
522 | 528 | if (iteratee != null) iteratee = cb(iteratee, context); |
523 | 529 | var result = []; |
524 | 530 | var seen = []; |
525 | | - for (var i = 0, length = array.length; i < length; i++) { |
| 531 | + for (var i = 0, length = getLength(array); i < length; i++) { |
526 | 532 | var value = array[i], |
527 | 533 | computed = iteratee ? iteratee(value, i, array) : value; |
528 | 534 | if (isSorted) { |
|
549 | 555 | // Produce an array that contains every item shared between all the |
550 | 556 | // passed-in arrays. |
551 | 557 | _.intersection = function(array) { |
552 | | - if (array == null) return []; |
553 | 558 | var result = []; |
554 | 559 | var argsLength = arguments.length; |
555 | | - for (var i = 0, length = array.length; i < length; i++) { |
| 560 | + for (var i = 0, length = getLength(array); i < length; i++) { |
556 | 561 | var item = array[i]; |
557 | 562 | if (_.contains(result, item)) continue; |
558 | 563 | for (var j = 1; j < argsLength; j++) { |
|
581 | 586 | // Complement of _.zip. Unzip accepts an array of arrays and groups |
582 | 587 | // each array's elements on shared indices |
583 | 588 | _.unzip = function(array) { |
584 | | - var length = array && _.max(array, 'length').length || 0; |
| 589 | + var length = array && _.max(array, getLength).length || 0; |
585 | 590 | var result = Array(length); |
586 | 591 |
|
587 | 592 | for (var index = 0; index < length; index++) { |
|
595 | 600 | // the corresponding values. |
596 | 601 | _.object = function(list, values) { |
597 | 602 | var result = {}; |
598 | | - for (var i = 0, length = list && list.length; i < length; i++) { |
| 603 | + for (var i = 0, length = getLength(list); i < length; i++) { |
599 | 604 | if (values) { |
600 | 605 | result[list[i]] = values[i]; |
601 | 606 | } else { |
|
609 | 614 | function createPredicateIndexFinder(dir) { |
610 | 615 | return function(array, predicate, context) { |
611 | 616 | predicate = cb(predicate, context); |
612 | | - var length = array != null && array.length; |
| 617 | + var length = getLength(array); |
613 | 618 | var index = dir > 0 ? 0 : length - 1; |
614 | 619 | for (; index >= 0 && index < length; index += dir) { |
615 | 620 | if (predicate(array[index], index, array)) return index; |
|
627 | 632 | _.sortedIndex = function(array, obj, iteratee, context) { |
628 | 633 | iteratee = cb(iteratee, context, 1); |
629 | 634 | var value = iteratee(obj); |
630 | | - var low = 0, high = array.length; |
| 635 | + var low = 0, high = getLength(array); |
631 | 636 | while (low < high) { |
632 | 637 | var mid = Math.floor((low + high) / 2); |
633 | 638 | if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; |
|
638 | 643 | // Generator function to create the indexOf and lastIndexOf functions |
639 | 644 | function createIndexFinder(dir, predicateFind, sortedIndex) { |
640 | 645 | return function(array, item, idx) { |
641 | | - var i = 0, length = array ? array.length : -1; |
| 646 | + var i = 0, length = getLength(array); |
642 | 647 | if (typeof idx == 'number') { |
643 | 648 | if (dir > 0) { |
644 | 649 | i = idx >= 0 ? idx : Math.max(idx + length, i); |
|
1136 | 1141 | } |
1137 | 1142 | // Assume equality for cyclic structures. The algorithm for detecting cyclic |
1138 | 1143 | // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. |
1139 | | - |
| 1144 | + |
1140 | 1145 | // Initializing stack of traversed objects. |
1141 | 1146 | // It's done here since we only need them for objects and arrays comparison. |
1142 | 1147 | aStack = aStack || []; |
|
1287 | 1292 |
|
1288 | 1293 | _.noop = function(){}; |
1289 | 1294 |
|
1290 | | - _.property = function(key) { |
1291 | | - return function(obj) { |
1292 | | - return obj == null ? void 0 : obj[key]; |
1293 | | - }; |
1294 | | - }; |
| 1295 | + _.property = property; |
1295 | 1296 |
|
1296 | 1297 | // Generates a function for a given object that returns a given property. |
1297 | 1298 | _.propertyOf = function(obj) { |
|
1300 | 1301 | }; |
1301 | 1302 | }; |
1302 | 1303 |
|
1303 | | - // Returns a predicate for checking whether an object has a given set of |
| 1304 | + // Returns a predicate for checking whether an object has a given set of |
1304 | 1305 | // `key:value` pairs. |
1305 | 1306 | _.matcher = _.matches = function(attrs) { |
1306 | 1307 | attrs = _.extendOwn({}, attrs); |
|
1527 | 1528 | // Provide unwrapping proxy for some methods used in engine operations |
1528 | 1529 | // such as arithmetic and JSON stringification. |
1529 | 1530 | _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; |
1530 | | - |
| 1531 | + |
1531 | 1532 | _.prototype.toString = function() { |
1532 | 1533 | return '' + this._wrapped; |
1533 | 1534 | }; |
|
0 commit comments