Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(isArray): support Array subclasses in angular.isArray()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
thorn0 authored and gkalpak committed Feb 1, 2018
1 parent 67f54b6 commit e3ece2f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

}

Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit e3ece2f

Please sign in to comment.