Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does jQuery create Array-Objects?

At first I thought it was just assigning obj[0], obj[1], obj[2], etc. to the jQuery object before returning it, and that the length is manually assigned. But no, since console.log logs an array and not an object.

I took a quick look at the jQuery source but since I'm not familiar with it I didn't crack it easily. jQuery.makeArray popped first, but it turned out to be the opposite of what I'm looking for, you actually lose the object methods by using it.

My first guess is initiating the array first, and then copying all the properties and methods from the object to it.

Does anybody with the jQuery source code experience have a clear answer to this?

like image 946
treznik Avatar asked Oct 04 '11 16:10

treznik


People also ask

How do I create an array in jQuery?

Syntax And Declaration:var arr1=[]; var arr2=[1,2,3]; var arr2=["India","usa","uk"]; Type of Array: The type of an array is “object“. Iteration Approach: We use the length property of the array to iterate in the array.

How is array an object in JavaScript?

The Array object lets you store multiple values in a single variable. It stores a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

Why is JavaScript array an object?

An object in JavaScript is similar in structure to the associative array/dictionary seen in most object oriented languages - i.e., it has a set of key-value pairs. An array can be considered to be an object with the following properties/keys: Length - This can be 0 or above (non-negative). The array indices.

What does $() do in jQuery?

When a jQuery object is passed to the $() function, a clone of the object is created. This new jQuery object references the same DOM elements as the initial one.


2 Answers

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"]
like image 104
davin Avatar answered Nov 11 '22 15:11

davin


It's as simple as creating a new function and assigning it a new array as its prototype.

function ArrayLike() {}
ArrayLike.prototype = [];

So for example:

function ArrayLike() {}
ArrayLike.prototype = [];
ArrayLike.prototype.fromArray = function(arr) {
    for(var i = 0; i < arr.length; i++)
        this.push(arr[i]);
};
ArrayLike.prototype.foo = function() {
    console.log("foo", this);
};

var a = new ArrayLike();
a.fromArray([1, 2]);
console.log(a);
a.foo();

http://jsfiddle.net/Xeon06/fUgaf/

like image 36
Alex Turpin Avatar answered Nov 11 '22 15:11

Alex Turpin