| 'use strict'; |
| |
| var iteratorSymbol = require('es6-symbol').iterator |
| , isArguments = require('../../function/is-arguments') |
| , isFunction = require('../../function/is-function') |
| , toPosInt = require('../../number/to-pos-integer') |
| , callable = require('../../object/valid-callable') |
| , validValue = require('../../object/valid-value') |
| , isString = require('../../string/is-string') |
| |
| , isArray = Array.isArray, call = Function.prototype.call |
| , desc = { configurable: true, enumerable: true, writable: true, value: null } |
| , defineProperty = Object.defineProperty; |
| |
| module.exports = function (arrayLike/*, mapFn, thisArg*/) { |
| var mapFn = arguments[1], thisArg = arguments[2], Constructor, i, j, arr, l, code, iterator |
| , result, getIterator, value; |
| |
| arrayLike = Object(validValue(arrayLike)); |
| |
| if (mapFn != null) callable(mapFn); |
| if (!this || (this === Array) || !isFunction(this)) { |
| // Result: Plain array |
| if (!mapFn) { |
| if (isArguments(arrayLike)) { |
| // Source: Arguments |
| l = arrayLike.length; |
| if (l !== 1) return Array.apply(null, arrayLike); |
| arr = new Array(1); |
| arr[0] = arrayLike[0]; |
| return arr; |
| } |
| if (isArray(arrayLike)) { |
| // Source: Array |
| arr = new Array(l = arrayLike.length); |
| for (i = 0; i < l; ++i) arr[i] = arrayLike[i]; |
| return arr; |
| } |
| } |
| arr = []; |
| } else { |
| // Result: Non plain array |
| Constructor = this; |
| } |
| |
| if (!isArray(arrayLike)) { |
| if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) { |
| // Source: Iterator |
| iterator = callable(getIterator).call(arrayLike); |
| if (Constructor) arr = new Constructor(); |
| result = iterator.next(); |
| i = 0; |
| while (!result.done) { |
| value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value; |
| if (!Constructor) { |
| arr[i] = value; |
| } else { |
| desc.value = value; |
| defineProperty(arr, i, desc); |
| } |
| result = iterator.next(); |
| ++i; |
| } |
| l = i; |
| } else if (isString(arrayLike)) { |
| // Source: String |
| l = arrayLike.length; |
| if (Constructor) arr = new Constructor(); |
| for (i = 0, j = 0; i < l; ++i) { |
| value = arrayLike[i]; |
| if ((i + 1) < l) { |
| code = value.charCodeAt(0); |
| if ((code >= 0xD800) && (code <= 0xDBFF)) value += arrayLike[++i]; |
| } |
| value = mapFn ? call.call(mapFn, thisArg, value, j) : value; |
| if (!Constructor) { |
| arr[j] = value; |
| } else { |
| desc.value = value; |
| defineProperty(arr, j, desc); |
| } |
| ++j; |
| } |
| l = j; |
| } |
| } |
| if (l === undefined) { |
| // Source: array or array-like |
| l = toPosInt(arrayLike.length); |
| if (Constructor) arr = new Constructor(l); |
| for (i = 0; i < l; ++i) { |
| value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i]; |
| if (!Constructor) { |
| arr[i] = value; |
| } else { |
| desc.value = value; |
| defineProperty(arr, i, desc); |
| } |
| } |
| } |
| if (Constructor) { |
| desc.value = null; |
| arr.length = l; |
| } |
| return arr; |
| }; |