As for my understanding 'ArrayLike' type in JavaScript is an object with own numeric positive integer keys, not necesary in successive order(sparse arrays etc.), where object's (int) .length
property is greater of them all, right? I came across dozen of explanations of the thing but every one of them gave diferent point of view, so I've wrote the function that finds max (int) key, trashes .length
property (to prevent Math.max()
yielding NaN
value, wich pares false
to anything) leaving the rest of object's own keys intact. If all of them are numerics it gives back max one, if not it gives NaN
(returning false
as result), and pared it's outputs with accepted jQuery equivalent function's results on same values. All explanations are wele. Here's the code I've ran:
// /jQuery version
function isArraylike(obj) {
// casted the obj parameter to Object here
// because some primitive values was throwing an error
// not supporting .property access or 'in' operand
// it doesn't change the logic just converts them to equivalent wrapped types
var length = (obj = Object(obj)).length,
type = jQuery.type(obj);
if (type === "function" || jQuery.isWindow(obj)) {
return false;
}
if (obj.nodeType === 1 && length) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && (length - 1) in obj;
}
// and my version
function isalike(o) {
try {
o.length;
return (Math.max.apply(Math,
erase(Object.keys(o), "length")
) < o.length);
} catch (e) {}
return false;
function erase(arr, val) {
var idx;
((idx = arr.indexOf(val)) != -1) && arr.splice(idx, 1);
return arr;
}
function s(arg) {
return Array.prototype.slice.call(arg, 0);
}
}
// and tests cases that came to my mind
// first boolean value in side ment is jq's output
// second is '.isalike()' function's output
var a =
{
0: [], // #0 true true
1: new Array, // #1 true true
2: new Array(10), // #2 true true
3: {}, // #3 false false
4: {length:0}, // #4 true true
5: {length:"0"}, // #5 false true
6: {length:"asd"}, // #6 false false
7: {length:false}, // #7 false true
8: {length:true}, // #8 false true
9: {length:null}, // #9 false true
10: {length:0, 0:1}, // #10 true false
11: {length:"0", 0:1}, // #11 false false
12: {length:0, 1:1}, // #12 true false
13: {length:0, 2:1}, // #13 true false
14: {length:"asd", 0:1}, // #14 false false
15: {length:0, x1:1}, // #15 true false
16: {length:0, 0:1, x1:1, x2:1}, // #16 true false
17: {length:1}, // #17 false true
18: {length:1, 0:1}, // #18 true true
19: {length:1, 1:1}, // #19 false false
20: {length:1, 2:1}, // #20 false false
21: {length:1, 0:1, x1:1}, // #21 true false
22: {length:2, 0:1}, // #22 false true
23: {length:2, 1:1}, // #23 true true
24: {length:2, 2:1}, // #24 false false
25: {length:2, 3:1}, // #25 false false
26: {length:2, 1:1, x1:1}, // #26 true false
27: window, // #27 false false
28: document, // #28 false false
29: function (x1) {}, // #29 false true
30: document.documentElement, // #30 false false
31: document.getElementsByTagName("*"), // #31 true false
32: document.body.childNodes, // #32 true true
33: document.body.children, // #33 true false
34: document.querySelectorAll("*"), // #34 true true
35: document.images, // #35 true true
36: window.frames, // #36 false false
37: $(), // #37 true true
38: $("*"), // #38 true false
39: "asd", // #39 true false
40: {length:NaN}, // #40 false false
41: {length:1/0} // #41 false true
};
console.clear();
for (
var it = 0,
end = 42;
it < end;
it++
) {
console.log( "#"+it, isArraylike(a[it]), isalike(a[it]) );
}
//
As for my understanding 'ArrayLike' type in JavaScript is an object with own numeric positive integer keys, not necesary in successive order(sparse arrays etc.), where object's (int) .length
property is greater of them all, right? I came across dozen of explanations of the thing but every one of them gave diferent point of view, so I've wrote the function that finds max (int) key, trashes .length
property (to prevent Math.max()
yielding NaN
value, wich pares false
to anything) leaving the rest of object's own keys intact. If all of them are numerics it gives back max one, if not it gives NaN
(returning false
as result), and pared it's outputs with accepted jQuery equivalent function's results on same values. All explanations are wele. Here's the code I've ran:
// /jQuery version
function isArraylike(obj) {
// casted the obj parameter to Object here
// because some primitive values was throwing an error
// not supporting .property access or 'in' operand
// it doesn't change the logic just converts them to equivalent wrapped types
var length = (obj = Object(obj)).length,
type = jQuery.type(obj);
if (type === "function" || jQuery.isWindow(obj)) {
return false;
}
if (obj.nodeType === 1 && length) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && (length - 1) in obj;
}
// and my version
function isalike(o) {
try {
o.length;
return (Math.max.apply(Math,
erase(Object.keys(o), "length")
) < o.length);
} catch (e) {}
return false;
function erase(arr, val) {
var idx;
((idx = arr.indexOf(val)) != -1) && arr.splice(idx, 1);
return arr;
}
function s(arg) {
return Array.prototype.slice.call(arg, 0);
}
}
// and tests cases that came to my mind
// first boolean value in side ment is jq's output
// second is '.isalike()' function's output
var a =
{
0: [], // #0 true true
1: new Array, // #1 true true
2: new Array(10), // #2 true true
3: {}, // #3 false false
4: {length:0}, // #4 true true
5: {length:"0"}, // #5 false true
6: {length:"asd"}, // #6 false false
7: {length:false}, // #7 false true
8: {length:true}, // #8 false true
9: {length:null}, // #9 false true
10: {length:0, 0:1}, // #10 true false
11: {length:"0", 0:1}, // #11 false false
12: {length:0, 1:1}, // #12 true false
13: {length:0, 2:1}, // #13 true false
14: {length:"asd", 0:1}, // #14 false false
15: {length:0, x1:1}, // #15 true false
16: {length:0, 0:1, x1:1, x2:1}, // #16 true false
17: {length:1}, // #17 false true
18: {length:1, 0:1}, // #18 true true
19: {length:1, 1:1}, // #19 false false
20: {length:1, 2:1}, // #20 false false
21: {length:1, 0:1, x1:1}, // #21 true false
22: {length:2, 0:1}, // #22 false true
23: {length:2, 1:1}, // #23 true true
24: {length:2, 2:1}, // #24 false false
25: {length:2, 3:1}, // #25 false false
26: {length:2, 1:1, x1:1}, // #26 true false
27: window, // #27 false false
28: document, // #28 false false
29: function (x1) {}, // #29 false true
30: document.documentElement, // #30 false false
31: document.getElementsByTagName("*"), // #31 true false
32: document.body.childNodes, // #32 true true
33: document.body.children, // #33 true false
34: document.querySelectorAll("*"), // #34 true true
35: document.images, // #35 true true
36: window.frames, // #36 false false
37: $(), // #37 true true
38: $("*"), // #38 true false
39: "asd", // #39 true false
40: {length:NaN}, // #40 false false
41: {length:1/0} // #41 false true
};
console.clear();
for (
var it = 0,
end = 42;
it < end;
it++
) {
console.log( "#"+it, isArraylike(a[it]), isalike(a[it]) );
}
//
Share
Improve this question
edited Jan 14, 2014 at 17:56
sudocdslash
asked Jan 14, 2014 at 14:20
sudocdslashsudocdslash
431 silver badge5 bronze badges
1
- 1 Slightly old but still informative blog post from Kangax. – Pointy Commented Jan 14, 2014 at 14:30
1 Answer
Reset to default 5I came across dozen of explanations of the thing but every one of them gave diferent point of view...
When you asked this question in 2014, there were different points of view. Since then, the JavaScript specification has given us a specific definition of "array-like".
The jQuery isArrayLike
function, as you can see from the code, imposes lots of requirements. The object must not be a function or a Window object; it must have a length
property; that property's value must be a number (without conversion), and it must have an element at index length - 1
.
JavaScript's definition is much less restrictive: The object must have a length
property that doesn't throw an error when you get it and convert it to a non-negative integer with a quite loose conversion. That's it. It can be a function, a Window object, a sparse array with no element at length - 1
, or any of several other things. All it needs is a length
property that doesn't throw when converted. That property's value could be the string "flibbertygibbit"
and that's fine (it'll be treated as 0
). From that link:
LengthOfArrayLike(obj)
The abstract operation LengthOfArrayLike takes argument obj (an Object) and returns either a normal pletion containing a non-negative integer or a throw pletion. It returns the value of the "length" property of an array-like object. It performs the following steps when called:
- Return ℝ(? ToLength(? Get(obj, "length"))).
An array-like object is any object for which this operation returns a normal pletion.
NOTE 1
Typically, an array-like object would also have some properties with integer index names. However, that is not a requirement of this definition.
(In that, ℝ just means "the mathematical value of" (so for instance, both +0 and -0 are just 0), and ToLength is the abstract specification operation that quite loosely converts just about anything to a non-negative integer number value.)