Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating array-like objects in JavaScript

Tags:

In JavaScript, there are objects that pretend to be arrays (or are "array-like"). Such objects are arguments, NodeLists (returned from getElementsByClassName, etc.), and jQuery objects.

When console.logged, 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.logged, 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.

like image 792
Rocket Hazmat Avatar asked Aug 09 '12 15:08

Rocket Hazmat


2 Answers

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.

like image 183
zzzzBov Avatar answered Sep 16 '22 19:09

zzzzBov


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.

like image 36
Bhojendra Rauniyar Avatar answered Sep 19 '22 19:09

Bhojendra Rauniyar