-
-
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 <alexthkloss@web.de> | |
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> |
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.
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.
I understand that no one sane will change
Object.prototype.toString
in runtime in real life. But anyway, it's not a good idea to rely on it.