-
-
Save atk/1034882 to your computer and use it in GitHub Desktop.
| // only set function if not already available | |
| Array.isArray || (Array.isArray = function( | |
| a // array or not array, this is the question | |
| ){ | |
| return | |
| // is not the string '[object Array]' and | |
| '' + a !== a && | |
| // test with Object.prototype.toString | |
| {}.toString.call(a) == '[object Array]' | |
| }); |
| Array.isArray||(Array.isArray=function(a){return''+a!==a&&{}.toString.call(a)=='[object Array]'}); |
| DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
| Version 2, December 2004 | |
| Copyright (C) 2011 Alex Kloss <[email protected]> | |
| Everyone is permitted to copy and distribute verbatim or modified | |
| copies of this license document, and changing it is allowed as long | |
| as the name is changed. | |
| DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
| TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
| 0. You just DO WHAT THE FUCK YOU WANT TO. |
| { | |
| "name": "isarray", | |
| "description": "polyfill an ES5-compatibile Array.isArray where needed.", | |
| "keywords": [ | |
| "polyfill", | |
| "es5", | |
| "isArray" | |
| ] | |
| } |
| <!DOCTYPE html> | |
| <title>Foo</title> | |
| <div>Expected value: <b>false, true, false, false, false, false</b></div> | |
| <div>Actual value: <b id="ret"></b></div> | |
| <script> | |
| // write a small example that shows off the API for your example | |
| // and tests it in one fell swoop. | |
| var isArray = Array.isArray||(Array.isArray=function(a){return''+a!==a{}.toString.call(a)=='[object Array]'}); | |
| document.getElementById( "ret" ).innerHTML = [isArray({}), isArray([]), isArray(""), isArray(0), isArray(true), isArray('[object Array]')]; | |
| </script> |
I think instanceof is the best solution.
I tried function(a){return[].concat(a)[0]!=a}. It is very short, but works up to 10 times slower (in node.js) when arg is not array.
Only 1 byte more length anyway, so let's go with the speedier version.
`instanceof´ is the wrong way. This will return false for foreign arrays. ie. arrays from other frames.
what @Kambfhase said. i prefer the original solution.
Changes reverted. Thanks for your comments!
still some room in there:
Array.isArray=Array.isArray||function(a){return toString.call(a)=='[object Array]'}Alas, the global native function toString is not available in IE6, for example, but ({}).toString is.
ah, didn't know that. you can still shave 3 bytes with the space after return, the triple equality, and the semicolon.
Thanks, done.
@Kambfhase, thanks for your correction!
If the order of operands is reversed we can drop the parens as when interpreter will get {} after == it waits for expression, not block. Either, in that case there's still no need to place whaitespace after return. :)
Array.isArray||Array.isArray=function(a){return'[object Array]'=={}.toString.call(a)}
Also, isn't it better not to assign Array.isArray to itself if it is exists?
{}.toString will lead to a SyntaxError in FF4 (and I guess in other Browsers, too). But the other point is valid. How to do so?
Array.isArray||(Array.isArray=...) seems right, any better ideas?
a.b||(a.b=...)is definitely a better patten than
a.b=a.b||...but the latter is shorter. doesn't make much of a difference here, but for Array.prototype.map it does. i'd rather have all shims be consistent, personally, but i guess it's a style thing.
@atk, that's strange. It works fine in my Fx 4.0.1
Strange enough, if I put it directly into my firebug console, it fails - but if I encapsulate it into a function, it works! Thanks again, @subzey
What about Array.isArray||(Array.isArray=function(a){return/Array/.test({}.toString.call(a))}) ?
@sebastien-p, It may conflict with typed arrays.
@subzey : ok, thanks :)
Not even that, what if I want to test a string containing "Array" at any point. Granted, if you try a string containing "[object Array]" it will return a false positive, too, yet this is less problematic, so if you want to be sure, add &&''+a!==a.
Maybe we could use the behavior of Array.prototype.concat so interpreter natively checks if argument is an array
Array.isArray?0:Array.isArray=function(a){return[].concat(a)!==a}@subzey
(function(a){return[].concat(a)!==a})('') // => true in firefox 10
Thanks, @atk!
Sorry, I missed [0]. That what I meant was
function(a){return[].concat(a)[0]!==a}Array.prototype.concat adds argument's contents to this array if arg is an array and otherwise it adds the argument itself.
I wanted to exploit this difference, but lately I've found an error: it won't work correctly if argument is an array and its 0'th value is the same object (var a = []; a[0] = a).
Ah, that explains it.
Added another fix. If you tried to test the format of '[object Array]', it would give you a false positive; by ensuring that we haven't got a string, this is now fixed, too.
Thanks for your comment, @subzey
I just ported the function from the ES5-Shim. The only other way to do this I could think of would be "a instanceOf Array". Since it's smaller, too, I think I will update this gist later.