99

There is two ways to figure out if an array is an array or an object. Using typeof item === "object"; will return true for an object and an array since arrays are relatively new to javascript and arrays are prototypes of objects(may have worded this wrong, feel free to correct me). So the two ways I know of to determine if an Array is an Array are:

Solution 1:

Array.isArray(item);

Solution 2:

item instanceof Array;

My questions are:

  1. What is the difference between these two solutions?
  2. Which of these two is the preferred solution?
  3. Which has a faster process time?
xlm
  • 6,854
  • 14
  • 53
  • 55
  • 2
    possible duplicate of [which is the best method used for checking isarray](http://stackoverflow.com/questions/19196539/which-is-the-best-method-used-for-checking-isarray) – Barmar Mar 09 '14 at 23:38
  • 4
    `isArray` is more generic. It works across iframes, which `isntanceof` does not. It also looks like that `isArray` will correctly recognize typed arrays in ES6. – Felix Kling Mar 09 '14 at 23:40
  • I’m sticking to `instanceof Array`, because: 1. the syntax is consistent with `instanceof (other classes)`, 2. for my Node.js, `Array`s and instances extending `Array` are constructed by the same `Array` in the same _execution context_. – Константин Ван Dec 04 '22 at 19:57
  • @FelixKling, you said “_`isArray` will correctly recognize typed arrays_,” but on my Chrome 107, `Array.isArray(new Uint8Array)` is `false`. – Константин Ван Dec 04 '22 at 20:00
  • @КонстантинВан You are correct, it doesn't look like it covers typed arrays. – Felix Kling Dec 05 '22 at 09:09

2 Answers2

93

1.What is the difference between these two solutions?

isArray is an ES5 method so not supported by older browsers, but it reliably determines if an object is an Array.

instanceof only checks if Array.prototype is on an object's [[Prototype]] chain. It fails when checking arrays across frames since the Array constructor used for the instance will likely be different to the one used for the test.

2.Which of these two is the preferred solution?

"Preferred" assumes some criterion for selection. Generally, the preferred method is something like:

if (Object.prototype.toString.call(obj) == '[object Array]')

which suits ES3 browsers and works across frames. If only ES5 browsers are in consideration, isArray is likely OK.

3.Which has a faster process time?

Largely irrelevant, since the processing time for both is negligible. Far more important to select the one that is reliable. An Array.isArray method can be added to browsers that don't have it built–in using:

if (!Array.isArray) {
    Array.isArray = function(obj) {
      return Object.prototype.toString.call(obj) == '[object Array]';
    }
}
Renato Gama
  • 16,431
  • 12
  • 58
  • 92
RobG
  • 142,382
  • 31
  • 172
  • 209
  • 2
    Wouldn't triple equals `===` be more reliable? – Vad Dec 10 '18 at 23:37
  • 9
    @vad—No. *Object.prototype.toString* always returns a string, so the results for `==` and `===` are identical. – RobG Dec 11 '18 at 01:24
  • Do note that in ES6+, an object may give itself a custom `toStringTag` resulting in `[object Array]` despite not actually being an array. I'm not sure if a fully reliable polyfill is possible for `Array.isArray` – CertainPerformance Feb 12 '19 at 06:40
  • 2
    @CertainPerformance—sure, but the above only suggests using a pollyfill where *Array.isArray* is not available, which excludes ECMAScript 2015 (introduced 4 years after ES5 and *isArray*) and later. – RobG Feb 12 '19 at 06:54
  • 2
    > "Largely irrelevant, since the processing time for both is negligible." That depends on how much you're calling these methods. In some context, e.g. games performance is ultra important. – HankMoody Mar 07 '19 at 13:24
  • @HankMoody—if you're coding for speed, then *isArray* should be avoided altogether, or at least called very infrequently. Also, performance should be tested across multiple implementations as it varies greatly. – RobG Mar 10 '19 at 13:00
  • 3
    I could argue though, that even if in a case `==` and `===` are identical, the latter still must be used. I mean, we dont choose selectively safety guidelines based on where we think they fit. We put them everywhere to form a habit, just in case something is forgotten, for a case we didnt think could happen or anything stupid happens. **It's not good practice to be selective with good practices, they should be applied everywhere or dont use them at all.** – Eksapsy Oct 22 '20 at 14:51
  • @Eksapsy— "must"? I think the fact that there are 73 answers covering more than a decade to [*Which equals operator (== vs ===) should be used in JavaScript comparisons?*](https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons) indicates it's a moot point. Just use one or the other consistently, and if strong typing is required, use Typescript. There is no evidence that `===` is "safer" than `==`. – RobG Oct 22 '20 at 23:50
  • 3
    @RobG, Eksapsy started with "I could argue", so why focus on his use of the word "must"? You statement "There is no evidence", though... What do you even mean with "evidence" when every frickin resource you can find on `==`/`===` talks about `==`'s ambiguity and how the operator is a mistake in the language. Isn't "**People being affected by the damn thing**" evidence to you? Just say "I don't see how" instead of "There is no evidence that", makes you look less discourteous... – Gust van de Wal May 20 '22 at 11:55
47
  1. Difference between Array.isArray(item) and item instanceof Array

    As Felix Kling mentioned in the comment, instanceof Array doesn't work across iframes. To give you a specific example, try the following code:

    var iframeEl = document.createElement('iframe');
    document.body.appendChild(iframeEl);
    iframeArray = window.frames[window.frames.length - 1].Array;
    
    var array1 = new Array(1,1,1,1);
    var array2 = new iframeArray(1,1,1,1);
    
    console.log(array1 instanceof Array);  // true    
    console.log(Array.isArray(array1));  // true
    
    console.log(array2 instanceof Array);  // false    
    console.log(Array.isArray(array2));  // true    
    

    As you see in the example above, array created with the Array constructor in iframe (i.e. array2) is not recognized as an array when you use instanceof Array. However, it is correctly identified as an array when using Array.isArray().

    If you are interested in knowing why instanceof Array doesn't work across different globals (i.e. iframe or window), you can read more about it on here.

  2. Which of these two is the preferred solution?

    In most cases instanceof Array should be enough. However, since instanceof Array doesn't work correctly across iframes/window, Array.isArray() would be more robust solution.

    Make sure to check for browser compatibility though. If you need to support IE 8 or less, Array.isArray() won't work (see Mozilla's doc).

  3. Which has a faster process time?

    According to this jsperf, instanceof Array is faster than Array.isArray(). Which makes sense, because Array.isArray() performs more robust checking and therefore takes a slight performance hit.

Shaheen Ghiassy
  • 7,397
  • 3
  • 40
  • 40
Brian Park
  • 2,557
  • 22
  • 21
  • 14
    Just came across this and would like to note that `Array.isArray()` in some browsers is now significantly faster than `instanceof Array` – Brant Sterling Wedel Aug 23 '17 at 21:17
  • Also, `instanceof Array` has a syntax consistent with `instanceof OtherClasses`. Unless you have multiple _execution contexts_, as in the browser environment, I recommend `instanceof Array` more. – Константин Ван Dec 04 '22 at 20:08
  • Actually, results show that `instanceof Array` is actually the slowest way to check if the property is an array. While `Array.isArray` is the fastest by far. https://www.measurethat.net/Benchmarks/ShowResult/441220 – Jordec Jul 17 '23 at 14:34