feat(isArray): support Array subclasses in angular.isArray()
Closes #15533 Closes #15541 BREAKING CHANGE: Previously, `angular.isArray()` was an alias for `Array.isArray()`. Therefore, objects that prototypally inherit from `Array` where not considered arrays. Now such objects are considered arrays too. This change affects several other methods that use `angular.isArray()` under the hood, such as `angular.copy()`, `angular.equals()`, `angular.forEach()`, and `angular.merge()`. This in turn affects how dirty checking treats objects that prototypally inherit from `Array` (e.g. MobX observable arrays). AngularJS will now be able to handle these objects better when copying or watching.
This commit is contained in:
committed by
George Kalpakas
parent
67f54b6600
commit
e3ece2fad9
+5
-4
@@ -219,8 +219,7 @@ function isArrayLike(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 || obj instanceof Array) || typeof obj.item === 'function');
|
||||
return isNumber(length) && (length >= 0 && (length - 1) in obj || typeof obj.item === 'function');
|
||||
|
||||
}
|
||||
|
||||
@@ -635,12 +634,14 @@ function isDate(value) {
|
||||
* @kind function
|
||||
*
|
||||
* @description
|
||||
* Determines if a reference is an `Array`. Alias of Array.isArray.
|
||||
* Determines if a reference is an `Array`.
|
||||
*
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is an `Array`.
|
||||
*/
|
||||
var isArray = Array.isArray;
|
||||
function isArray(arr) {
|
||||
return Array.isArray(arr) || arr instanceof Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
|
||||
@@ -1254,6 +1254,37 @@ describe('angular', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isArray', function() {
|
||||
|
||||
it('should return true if passed an `Array`', function() {
|
||||
expect(isArray([])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if passed an `Array` from a different window context', function() {
|
||||
var iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe); // No `contentWindow` if not attached to the DOM.
|
||||
var arr = new iframe.contentWindow.Array();
|
||||
document.body.removeChild(iframe); // Clean up.
|
||||
|
||||
expect(arr instanceof Array).toBe(false);
|
||||
expect(isArray(arr)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if passed an object prototypically inherited from `Array`', function() {
|
||||
function FooArray() {}
|
||||
FooArray.prototype = [];
|
||||
|
||||
expect(isArray(new FooArray())).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if passed non-array objects', function() {
|
||||
expect(isArray(document.body.childNodes)).toBe(false);
|
||||
expect(isArray({length: 0})).toBe(false);
|
||||
expect(isArray({length: 2, 0: 'one', 1: 'two'})).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('isArrayLike', function() {
|
||||
|
||||
it('should return false if passed a number', function() {
|
||||
|
||||
Reference in New Issue
Block a user