In JavaScript, there are objects that pretend to be arrays (or are "array-like"). Such objects are arguments
, NodeList
s (returned from getElementsByClassName
, etc.), and jQuery objects.
When console.log
ged, they appear as arrays, but they are not. I know that in order to be array-like, an object must have a length
property.
So I made an "object" like this:
function foo(){ this.length = 1; this[0] = "bar"; } var test = new foo;
When I console log(test)
, I get (as expected) a foo
object. I can "convert" it to an array using
Array.prototype.slice.call(test)
But, I don't want to convert it, I want it to be array-like. How do I make an array-like object, so that when it's console.log
ged, it appears as an array?
I tried setting foo.prototype = Array.prototype
, but console.log(new foo)
still shows a foo
object, and not an array.
Depends specifically on the console. For custom objects in Chrome's developer console, and Firebug you'll need both the length
and splice
properties. splice
will also have to be a function.
a = { length: 0, splice: function () {} } console.log(a); //[]
It's important to note, however, that there is no official standard.
The following code is used by jQuery (v1.11.1) internally to determine if an object should use a for
loop or a for..in
loop:
function isArraylike( obj ) { var length = 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; }
Note that it's possible to have an object that appears in the console as an array ([]
) but that gets iterated over with a for..in
loop in jQuery, or an object that appears as an object in the console ({}
) but that gets iterated over with a for
loop in jQuery.
The same question got into my mind as while we can use array like arguments
parameter:
function arrayLike() { console.log(typeof arguments) console.log(arguments) console.log(Array.from(arguments)) } arrayLike(1,2,3)
So, let's try creating our own array-like object:
let arrayLikeObject = { 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject))
Obviously, there's no length property defined so our arrayLikeObject
will only return an empty array. Now, let's try defining a length property:
let arrayLikeObject = { length: 2, 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject))
What if length is set different?
let arrayLikeObject = { length: 1, 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject)) // it will only return the value from first `0: 1`
let arrayLikeObject = { length: 5, 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject)) // other 3 values will be printed as undefined
But, I don't want to convert it...
You actually wanted to create an array, not array-like object. The array-like object must be converted like you said:
Array.prototype.slice.call(arrayLikeObject) // Or, [].slice.call(arrayLikeObject)
If you do try to use array methods on array-like object, then you'll get type error:
let arrayLikeObject = { length: 5, 0: 1, 1: 2 } console.log(arrayLikeObject.sort())
Thus, to use the array methods on arrayLikeObject, we need to convert it into array as we did in preceding examples using Array.from
.
Otherwise, you simply need to create an array:
let arr = [1,2] // I don't mean, you don't know
Other consideration:
You can't use it as constructor:
let arrayLikeObject = { length: 1, slice: function () { return 1 } } console.log(new arrayLikeObject) // Type error
In the following snippet, the result will be [undefined]
as the length property is set to 1 but there's no 0
indexed property:
let arrayLikeObject = { length: 1, slice: function () { return 1 } } console.log(Array.from(arrayLikeObject))
But if you set the length to 0, then the result will be an empty array []
because we're telling that we don't have any values in this array-like object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With