diff --git a/src/Angular.js b/src/Angular.js index fea935d0e316..574e85f265b6 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -191,11 +191,6 @@ var msie = document.documentMode; -function isNodeList(obj) { - return typeof obj.length == 'number' && - typeof obj.item == 'function'; -} - /** * @private * @param {*} obj @@ -207,15 +202,20 @@ function isArrayLike(obj) { // `null`, `undefined` and `window` are not array-like if (obj == null || isWindow(obj)) return false; - // arrays and strings are array like - if (isArray(obj) || isString(obj)) return true; + // arrays, strings and jQuery/jqLite objects are array like + // * jqLite is either the jQuery or jqLite constructor function + // * we have to check the existance of jqLite first as this method is called + // via the forEach method when constructing the jqLite object in the first place + if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true; // Support: iOS 8.2 (not reproducible in simulator) // "length" in obj used to prevent JIT error (gh-11508) var length = "length" in Object(obj) && obj.length; - // node lists and objects with suitable length characteristics are array-like - return (isNumber(length) && length >= 0 && (length - 1) in obj) || isNodeList(obj); + // NodeList objects (with `item` method) and + // other objects with suitable length characteristics are array-like + return isNumber(length) && + (length >= 0 && (length - 1) in obj || typeof obj.item == 'function'); } /** diff --git a/test/AngularSpec.js b/test/AngularSpec.js index e39471ed3bef..d5662bb53622 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -1129,6 +1129,11 @@ describe('angular', function() { forEach(jqObject, function(value, key) { log.push(key + ':' + value.innerHTML); }); expect(log).toEqual(['0:s1', '1:s2']); + + log = []; + jqObject = jqLite(""); + forEach(jqObject.children(), function(value, key) { log.push(key + ':' + value.innerHTML); }); + expect(log).toEqual([]); });