32

I'm wondering how jQuery constructs its array-like object. The key thing I'm trying to work out is how it manages to get the console to interpret it as an array and display it as such. I know it has something to do with the length property, but after playing a bit I can't quite figure it out.

I know this has no technical advantage over a normal array like object as in the example below. But I think it's an important semantic element when users are testing and debugging.

A normal Array like Object.

function foo(){
    // Array like objects have a length property and it's properties use integer
    // based sequential key names, e.g. 0,1,2,3,4,5,6 just like an array.
    this.length = 1;
    this[0] = 'hello'
}
// Just to make sure add the length property to the prototype to match the Array 
// prototype
foo.prototype.length = 0;

// Give the Array like object an Array method to test that it works     
foo.prototype.push = Array.prototype.push

// Create an Array like object 
var bar = new foo;

//test it 
bar.push('world');

console.log(bar);
// outputs 
{ 0: 'hello',
  1: 'world',
  length: 2,
  __proto__: foo
}

Where as jQuery would output

var jQArray = $('div')

console.log(jQArray);

// outputs
[<div></div>,<div></div>,<div></div>,<div></div>]

If you run

console.dir(jQArray)

// Outputs

{ 0: HTMLDivElement,
  1: HTMLDivElement,
  2: HTMLDivElement,
  3: HTMLDivElement,
  4: HTMLDivElement,
  context: HTMLDocument,
  length: 5,
  __proto__: Object[0]
 }

The proto of the jQuery object is especially interesting since its the Object and not jQuery.fn.init as would be expected, also the [0] indicates something as this is what you get when you.

console.dir([])
// outputs Array[0] as the object name or Array[x] x being the internal length of the
// Array

I have no idea how jQuery has set it's proto to be Object[0] but my guess is that answer lies somewhere in there. Anyone got any ideas?

2
  • I'm not sure about this, but couldn't you create your object then set its prototype to Array.prototype? It will then be an array-like object? Or no? Commented Jul 6, 2011 at 15:39
  • well as far as I know that will make it a normal array. But I also want to avoid that since I don't want to add all the Array methods to my object, in order to avoid confusion. As some Array methods will actually return a new Array, so when a user uses one of those methods all the other methods that where attached to my array like object will be lost. Commented Jul 6, 2011 at 15:47

2 Answers 2

43

The object has to have length and splice

> var x = {length:2, '0':'foo', '1':'bar', splice:function(){}}
> console.log(x);
['foo', 'bar']

and FYI, the Object[0] as the prototype is for exactly the same reason. The browser is seeing the prototype itself as an array because:

$.prototype.length == 0;
$.prototype.splice == [].splice;
Sign up to request clarification or add additional context in comments.

3 Comments

No need for splice if you don't need the object to print as an array with console.log(). length and properties like 0,1 will suffice to use the array methods.
@zyklus Do you happen to know if this is part of the ECMA spec (array-like objects) or is this a browser nicety?
@Usagi - AFAIK this has nothing to do with ECMA script and is just a random dev tools thing. There are a lot of "array-like" objects in JS, both in the language and user-created, so it's useful to show them as arrays if they implement some minimum subset of Array, this is just what the devs picked.
-1

Like this?

function foo() {
  this.push('hello');
}
foo.prototype = [];

var bar = new foo();
console.log(bar.length); // 1
console.log(bar); // ["hello"]

4 Comments

That has the same effect as the response I gave @JohnStrickler. I don't want to add all the Array methods to my Object to avoid confusion as some array methods actually return a new Array. So any other methods I attach to the object will be lost, when they are used.
jQuery object uses Array as its prototype. I think you can redefine this methods so they will return new foo object instead of regular array.
@Andrey M. - Please don't go saying stuff that you don't know for sure. jQuery does not use Array as it's prototype. It uses push, sort, and splice from Array, but that's it.
I took another look up the prototype Chain of the jQuery object and cannot find Array defined anywhere within it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.