jQuery creates what are called (in the ES standard) array-like objects. In particular, they have a length property, and also (which makes use of the length property) they have the relevant items placed under integer-based indices.
It's as simple as:
var arrayLike = {length: 3, 0:'first', 1:'second', 2:'third'};
Array.prototype.join.call(arrayLike, '|'); // "first|second|third"
If you take a look at the standard (15.4.4), particularly the Array.prototype
methods you'll see the following note under each and every one:
NOTE The * function is intentionally generic; it does not require that
its this value be an Array object. Therefore it can be transferred to
other kinds of objects for use as a method. Whether the * function can
be applied successfully to a host object is implementation-dependent.
If you look at the description of these algorithms, they pretty much just use the length property to iterate over the object (in our case an array-like object) and access the values behind those integer-based keys. For that reason they're generic and work on regular js objects with the relevant properties.
Essentially that's all jQuery does (if I remember correctly the building is done in sizzle, jquery's css selector engine). You can test this out/prove it in a variety of ways. For example, a standard js Array performs some magic when the length property is shortened, but the jquery object doesn't:
var arr = [1,2,3], $arr = $('div'); // assuming three divs
arr.length=2; arr[2]; // undefined
$arr.length=2; $arr[2]; // still references the div
http://jsfiddle.net/cnkB9/
So jquery's makeArray
converts the jquery array-like object, and makes it into an actual native js array, but as you said, then it doesn't have all the jquery methods attached.
As for why it shows up in the console, I refer to this excellent answer: What makes Firebug/Chrome console treat a custom object as an array? that explains that the presence of the length
property and splice
function allow it to appear like an array in most consoles. As is mentioned, that isn't the case in FF4's Web Console, which just shows you that it's not a native js array. Interestingly enough, the splice
function doesn't actually have to work, just be present, and be a function. For example:
>> console.log({length:2,0:'some',1:'thing',splice:new Function});
["some", "thing"]
NodeList
works like an array but isn't. – BoltClock♦ Oct 4 '11 at 16:59