|
379 | 379 | // iterate own properties using `Object.keys` if it's fast
|
380 | 380 | ' <% if (isKeysFast && useHas) { %>\n' +
|
381 | 381 | ' var ownIndex = -1,\n' +
|
382 |
| - ' ownProps = nativeKeys(iteratee),\n' + |
| 382 | + ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' + |
383 | 383 | ' length = ownProps.length;\n\n' +
|
384 | 384 | ' <%= objectBranch.beforeLoop %>;\n' +
|
385 | 385 | ' while (++ownIndex < length) {\n' +
|
386 | 386 | ' index = ownProps[ownIndex];\n' +
|
387 |
| - ' if (!(skipProto && index == \'prototype\')) {\n' + |
388 |
| - ' value = iteratee[index];\n' + |
389 |
| - ' <%= objectBranch.inLoop %>\n' + |
390 |
| - ' }\n' + |
| 387 | + ' <% if (!hasDontEnumBug) { %>if (!(skipProto && index == \'prototype\')) {\n <% } %>' + |
| 388 | + ' value = iteratee[index];\n' + |
| 389 | + ' <%= objectBranch.inLoop %>\n' + |
| 390 | + ' <% if (!hasDontEnumBug) { %>}\n<% } %>' + |
391 | 391 | ' }' +
|
392 | 392 |
|
393 | 393 | // else using a for-in loop
|
|
946 | 946 | */
|
947 | 947 | var shimKeys = createIterator({
|
948 | 948 | 'args': 'object',
|
949 |
| - 'exit': 'if (!(object && objectTypes[typeof object])) throw TypeError()', |
950 | 949 | 'init': '[]',
|
951 | 950 | 'inLoop': 'result.push(index)'
|
952 | 951 | });
|
|
1231 | 1230 | * // => true
|
1232 | 1231 | */
|
1233 | 1232 | function has(object, property) {
|
1234 |
| - return hasOwnProperty.call(object, property); |
| 1233 | + return object ? hasOwnProperty.call(object, property) : false; |
1235 | 1234 | }
|
1236 | 1235 |
|
1237 | 1236 | /**
|
|
1282 | 1281 | * // => true
|
1283 | 1282 | */
|
1284 | 1283 | function isElement(value) {
|
1285 |
| - return !!(value && value.nodeType == 1); |
| 1284 | + return value ? value.nodeType == 1 : false; |
1286 | 1285 | }
|
1287 | 1286 |
|
1288 | 1287 | /**
|
|
1547 | 1546 | // http://es5.github.com/#x8
|
1548 | 1547 | // and avoid a V8 bug
|
1549 | 1548 | // http://code.google.com/p/v8/issues/detail?id=2291
|
1550 |
| - return value && objectTypes[typeof value]; |
| 1549 | + return value ? objectTypes[typeof value] : false; |
1551 | 1550 | }
|
1552 | 1551 |
|
1553 | 1552 | /**
|
|
1686 | 1685 | * // => ['one', 'two', 'three'] (order is not guaranteed)
|
1687 | 1686 | */
|
1688 | 1687 | var keys = !nativeKeys ? shimKeys : function(object) {
|
| 1688 | + var type = typeof object; |
| 1689 | + |
1689 | 1690 | // avoid iterating over the `prototype` property
|
1690 |
| - return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype') |
1691 |
| - ? shimKeys(object) |
1692 |
| - : nativeKeys(object); |
| 1691 | + if (type == 'function' && propertyIsEnumerable.call(object, 'prototype')) { |
| 1692 | + return shimKeys(object); |
| 1693 | + } |
| 1694 | + return object && objectTypes[type] |
| 1695 | + ? nativeKeys(object) |
| 1696 | + : []; |
1693 | 1697 | };
|
1694 | 1698 |
|
| 1699 | + /** |
| 1700 | + * Merges enumerable properties of the source object(s) into the `destination` |
| 1701 | + * object. Subsequent sources will overwrite propery assignments of previous |
| 1702 | + * sources. |
| 1703 | + * |
| 1704 | + * @static |
| 1705 | + * @memberOf _ |
| 1706 | + * @category Objects |
| 1707 | + * @param {Object} object The destination object. |
| 1708 | + * @param {Object} [source1, source2, ...] The source objects. |
| 1709 | + * @param {Object} [indicator] Internally used to indicate that the `stack` |
| 1710 | + * argument is an array of traversed objects instead of another source object. |
| 1711 | + * @param {Array} [stack=[]] Internally used to keep track of traversed objects |
| 1712 | + * to avoid circular references. |
| 1713 | + * @returns {Object} Returns the destination object. |
| 1714 | + * @example |
| 1715 | + * |
| 1716 | + * var stooges = [ |
| 1717 | + * { 'name': 'moe' }, |
| 1718 | + * { 'name': 'larry' } |
| 1719 | + * ]; |
| 1720 | + * |
| 1721 | + * var ages = [ |
| 1722 | + * { 'age': 40 }, |
| 1723 | + * { 'age': 50 } |
| 1724 | + * ]; |
| 1725 | + * |
| 1726 | + * _.merge(stooges, ages); |
| 1727 | + * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] |
| 1728 | + */ |
| 1729 | + var merge = createIterator(extendIteratorOptions, { |
| 1730 | + 'args': 'object, source, indicator, stack', |
| 1731 | + 'top': |
| 1732 | + 'var destValue, found, isArr, stackLength, recursive = indicator == isPlainObject;\n' + |
| 1733 | + 'if (!recursive) stack = [];\n' + |
| 1734 | + 'for (var argsIndex = 1, argsLength = recursive ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' + |
| 1735 | + ' if (iteratee = arguments[argsIndex]) {', |
| 1736 | + 'inLoop': |
| 1737 | + 'if (value && ((isArr = isArray(value)) || isPlainObject(value))) {\n' + |
| 1738 | + ' found = false; stackLength = stack.length;\n' + |
| 1739 | + ' while (stackLength--) {\n' + |
| 1740 | + ' if (found = stack[stackLength].source == value) break\n' + |
| 1741 | + ' }\n' + |
| 1742 | + ' if (found) {\n' + |
| 1743 | + ' result[index] = stack[stackLength].value\n' + |
| 1744 | + ' } else {\n' + |
| 1745 | + ' destValue = (destValue = result[index]) && isArr\n' + |
| 1746 | + ' ? (isArray(destValue) ? destValue : [])\n' + |
| 1747 | + ' : (isPlainObject(destValue) ? destValue : {});\n' + |
| 1748 | + ' stack.push({ value: destValue, source: value });\n' + |
| 1749 | + ' result[index] = callee(destValue, value, isPlainObject, stack)\n' + |
| 1750 | + ' }\n' + |
| 1751 | + '} else if (value != null) {\n' + |
| 1752 | + ' result[index] = value\n' + |
| 1753 | + '}' |
| 1754 | + }); |
| 1755 | + |
1695 | 1756 | /**
|
1696 | 1757 | * Creates a shallow clone of `object` composed of the specified properties.
|
1697 | 1758 | * Property names may be specified as individual arguments or as arrays of
|
|
1709 | 1770 | * // => { 'name': 'moe', 'age': 40 }
|
1710 | 1771 | */
|
1711 | 1772 | function pick(object) {
|
| 1773 | + var result = {}; |
| 1774 | + if (!object) { |
| 1775 | + return result; |
| 1776 | + } |
1712 | 1777 | var prop,
|
1713 | 1778 | index = 0,
|
1714 | 1779 | props = concat.apply(ArrayProto, arguments),
|
1715 |
| - length = props.length, |
1716 |
| - result = {}; |
| 1780 | + length = props.length; |
1717 | 1781 |
|
1718 | 1782 | // start `index` at `1` to skip `object`
|
1719 | 1783 | while (++index < length) {
|
|
2025 | 2089 | */
|
2026 | 2090 | var map = createIterator(baseIteratorOptions, mapIteratorOptions);
|
2027 | 2091 |
|
2028 |
| - /** |
2029 |
| - * Merges enumerable properties of the source object(s) into the `destination` |
2030 |
| - * object. Subsequent sources will overwrite propery assignments of previous |
2031 |
| - * sources. |
2032 |
| - * |
2033 |
| - * @static |
2034 |
| - * @memberOf _ |
2035 |
| - * @category Objects |
2036 |
| - * @param {Object} object The destination object. |
2037 |
| - * @param {Object} [source1, source2, ...] The source objects. |
2038 |
| - * @param {Object} [indicator] Internally used to indicate that the `stack` |
2039 |
| - * argument is an array of traversed objects instead of another source object. |
2040 |
| - * @param {Array} [stack=[]] Internally used to keep track of traversed objects |
2041 |
| - * to avoid circular references. |
2042 |
| - * @returns {Object} Returns the destination object. |
2043 |
| - * @example |
2044 |
| - * |
2045 |
| - * var stooges = [ |
2046 |
| - * { 'name': 'moe' }, |
2047 |
| - * { 'name': 'larry' } |
2048 |
| - * ]; |
2049 |
| - * |
2050 |
| - * var ages = [ |
2051 |
| - * { 'age': 40 }, |
2052 |
| - * { 'age': 50 } |
2053 |
| - * ]; |
2054 |
| - * |
2055 |
| - * _.merge(stooges, ages); |
2056 |
| - * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] |
2057 |
| - */ |
2058 |
| - var merge = createIterator(extendIteratorOptions, { |
2059 |
| - 'args': 'object, source, indicator, stack', |
2060 |
| - 'top': |
2061 |
| - 'var destValue, found, isArr, stackLength, recursive = indicator == isPlainObject;\n' + |
2062 |
| - 'if (!recursive) stack = [];\n' + |
2063 |
| - 'for (var argsIndex = 1, argsLength = recursive ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' + |
2064 |
| - ' if (iteratee = arguments[argsIndex]) {', |
2065 |
| - 'inLoop': |
2066 |
| - 'if (value && ((isArr = isArray(value)) || isPlainObject(value))) {\n' + |
2067 |
| - ' found = false; stackLength = stack.length;\n' + |
2068 |
| - ' while (stackLength--) {\n' + |
2069 |
| - ' if (found = stack[stackLength].source == value) break\n' + |
2070 |
| - ' }\n' + |
2071 |
| - ' if (found) {\n' + |
2072 |
| - ' result[index] = stack[stackLength].value\n' + |
2073 |
| - ' } else {\n' + |
2074 |
| - ' destValue = (destValue = result[index]) && isArr\n' + |
2075 |
| - ' ? (isArray(destValue) ? destValue : [])\n' + |
2076 |
| - ' : (isPlainObject(destValue) ? destValue : {});\n' + |
2077 |
| - ' stack.push({ value: destValue, source: value });\n' + |
2078 |
| - ' result[index] = callee(destValue, value, isPlainObject, stack)\n' + |
2079 |
| - ' }\n' + |
2080 |
| - '} else if (value != null) {\n' + |
2081 |
| - ' result[index] = value\n' + |
2082 |
| - '}' |
2083 |
| - }); |
2084 |
| - |
2085 | 2092 | /**
|
2086 | 2093 | * Retrieves the value of a specified property from all elements in
|
2087 | 2094 | * the `collection`.
|
|
0 commit comments