Creating custom-array-like objects

– when you log a jQuery object, it shows you an array, despite the fact that it is a collection.

console.log ( $( ) ); //returns [] , an empty array

– but if you alert the collection, it tells you it is an object

alert ( $( ) ); //returns [Object object]

– if I try to check whether the collection is actually an array, that is by doing

$( ) instanceof Array ; //returns false

instanceof verifies any item by checking its prototype and in the jQuery source, I was not able to find any such inheritances from Array.

I was trying to figure out how could this happen – why console.log treats it differently than alert () and how could instanceof not work on an array.

That’s when I found a comment on a stack-overflow question:

A jQuery Object is not based on an array, it's an object which behaves "array-like" by adding .length and .splice() –  jAndy Aug 8 '11 at 9:27

It led me to a discovery of the same on MDN:

The last browser to use JavaScript 1.2 was Netscape Navigator 4, so you can depend on splice() always returning an array.

Aha! moment

I have now figured out a definitive way to create a custom array-like-object that beats console.log:

Note: creating totally custom arrays need a different approach as discussed in another post

The idea is to exploit 3 key properties: length, splice and Array.prototype

function MyArray(  ){
  return new MyArray.prototype.init( arguments );
}

MyArray.prototype = {
  el : [],
  add : function ( element ) {
    this.el.push (element);
  },
  addAll : function ( args ){
    if ( ! args instanceof Array ) return;
    this.el.concat ( args );
  },
  length : function (){
    return this.el.length;
  },
  splice : function (){
    return this.el.splice;
  },
  init : function ( args ){
    this.el = [].slice.call(args);
    return [].slice.call(args)  ;
  }
}

MyArray.prototype.init.prototype = Array.prototype;

//Now you can try:
a = new MyArray(1,2,3,4);
>> [1, 2, 3, 4]
a.length;
>> 4
a.push(1);
>> 5
a;
>> [1, 2, 3, 4, 1]
a.push(0);
>> 6
a;
>> [1, 2, 3, 4, 1, 0]
a instanceof Array;
>> true

//but this doesn't inherit from MyArray, so
a instanceof MyArray;
>> false

//Conclusion: We've just an array like object, not actually a custom array

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s