diff --git a/lodash.js b/lodash.js index 2e5732aae..43c1695a3 100644 --- a/lodash.js +++ b/lodash.js @@ -4092,18 +4092,6 @@ return func == null ? undefined : func.apply(object, args); } - /** - * Checks if `value` is array-like. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - */ - function isArrayLike(value) { - return value != null && - !(typeof value == 'function' && objToString.call(value) == funcTag) && isLength(getLength(value)); - } - /** * Checks if the provided arguments are from an iteratee call. * @@ -8173,6 +8161,33 @@ */ var isArray = Array.isArray; + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @type Function + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(function() { return arguments; }()); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && + !(typeof value == 'function' && objToString.call(value) == funcTag) && isLength(getLength(value)); + } + /** * Checks if `value` is classified as a boolean primitive or object. * @@ -11829,6 +11844,7 @@ lodash.inRange = inRange; lodash.isArguments = isArguments; lodash.isArray = isArray; + lodash.isArrayLike = isArrayLike; lodash.isBoolean = isBoolean; lodash.isDate = isDate; lodash.isElement = isElement; diff --git a/test/test.js b/test/test.js index 534cb9890..d82f5e0fe 100644 --- a/test/test.js +++ b/test/test.js @@ -6169,6 +6169,55 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isArrayLike'); + + (function() { + var args = arguments; + + test('should return `true` for array-like values', 1, function() { + var values = [args, [1, 2, 3], { '0': 1, 'length': 1 }, 'a'], + expected = _.map(values, _.constant(true)), + actual = _.map(values, _.isArrayLike); + + deepEqual(actual, expected); + }); + + test('should return `false` for non-arrays', 10, function() { + var expected = _.map(falsey, function(value) { return value === ''; }); + + var actual = _.map(falsey, function(value, index) { + return index ? _.isArrayLike(value) : _.isArrayLike(); + }); + + deepEqual(actual, expected); + + strictEqual(_.isArrayLike(true), false); + strictEqual(_.isArrayLike(new Date), false); + strictEqual(_.isArrayLike(new Error), false); + strictEqual(_.isArrayLike(_), false); + strictEqual(_.isArrayLike(slice), false); + strictEqual(_.isArrayLike(), false); + strictEqual(_.isArrayLike(1), false); + strictEqual(_.isArrayLike(NaN), false); + strictEqual(_.isArrayLike(/x/), false); + }); + + test('should work with an array from another realm', 1, function() { + if (_._object) { + var values = [_._arguments, _._array, _._string], + expected = _.map(values, _.constant(true)), + actual = _.map(values, _.isArrayLike); + + deepEqual(actual, expected); + } + else { + skipTest(); + } + }); + }(1, 2, 3)); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.isBoolean'); (function() { @@ -8133,11 +8182,11 @@ }); }); - test('should not error on host objects (test in IE)', 16, function() { + test('should not error on host objects (test in IE)', 17, function() { var funcs = [ - 'isArguments', 'isArray', 'isBoolean', 'isDate', 'isElement', - 'isError', 'isFinite', 'isFunction', 'isNaN', 'isNil', 'isNull', - 'isNumber', 'isObject', 'isRegExp', 'isString', 'isUndefined' + 'isArguments', 'isArray', 'isArrayLike', 'isBoolean', 'isDate', + 'isElement', 'isError', 'isFinite', 'isFunction', 'isNaN', 'isNil', + 'isNull', 'isNumber', 'isObject', 'isRegExp', 'isString', 'isUndefined' ]; _.each(funcs, function(methodName) { @@ -17310,6 +17359,7 @@ 'includes', 'isArguments', 'isArray', + 'isArrayLike', 'isBoolean', 'isDate', 'isElement', @@ -17550,7 +17600,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); - test('should accept falsey arguments', 229, function() { + test('should accept falsey arguments', 230, function() { var emptyArrays = _.map(falsey, _.constant([])); _.each(acceptFalsey, function(methodName) {