I'm relatively new to javascript and very new to jquery.
I have noticed that the jquery set returned by jQuery() selector shares a lot of similarities with javascript array e.g. elements in the jquery set can be accessed by the square bracket [] syntax
So I was wondering, is there any foundamental difference between jquery set and javascript array? Or they can be thought of as two ways of representing the same thing?
From their own docs (found here):
The jQuery object itself behaves much like an array; it has a length
property and the elements in the object can be accessed by their
numeric indices [0] to [length-1]. Note that a jQuery object is not
actually a Javascript Array object, so it does not have all the
methods of a true Array object such as join().
So a jquery object is sort of array like, but it's not an array. Basically, an array will have methods the jquery object lacks, and the jquery object has methods that arrays lack. I would generally try not to treat the jquery objects as arrays, and instead try to use a jquery method whenever tempted to use an array method (ie, use .each instead of the array method .forEach).
EDIT:
After reading more about the jquery objects, they do share a lot of methods with arrays, such as .find. Moreover, it also provides a .toArray method which can be used to convert the jquery object into an actual javascript array.
As the person who was responsible for this jQuery feature, I thought I would share some historical notes.
If you study the jQuery API, you may notice something odd: the object returned by $()/jQuery() is not only an "array-like" object with a .length property and [i] access to its elements, but it also has a couple of fairly redundant methods: .get(i) and .size().
.get(i) is very similar to an array's [i]: it returns one of the elements of the jQuery array/object. And .size() is the same as .length.
In fact, if you look at the implementation of .size() you will see that it simply returns the .length property:
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
There is a little more to .get(). If you don't pass an argument, it is the same as .toArray(), and if you do pass an argument it allows both positive and negative indexes. Negative indexes count backwards from the end of the array similar to Python or Ruby.
But for the simple case of a non-negative index, .get(i) boils down to:
// Get the Nth element in the matched element set
get: function( num ) {
return this[ num ];
},
Why all this redundancy? .size() and .get(i) just do the same thing as the usual .length or [i], so why have both?
In the very first jQuery release in January 2006 (long before 1.0), the object returned by $() was not an "array-like" object. It was just a JavaScript object with .get(i) and .size() methods. The actual list of DOM elements was a separate "private" property of the jQuery object, and you were supposed to use those methods to access its elements and length.
As I worked with that initial jQuery release, it seemed a bit clumsy to have to call .get(i) and .size() to access the elements of the returned jQuery object. This object seemed to be a lot like an array, but you couldn't access its elements the same way as a normal array. So I thought, why not make it act more like a real array with [i] and .length?
It was a fairly simple change to do that, so we ran with it, but we kept the old .get(i) and size() methods for compatibility with code that already used those.
Now a confession: I don't remember the reason for making the return object an array-like object instead of directly inheriting from Array. (It was 11 years ago after all!)
We would have preferred making this object an actual array, but there was a good reason why that would work. Perhaps I will remember after sleeping on it, but in the meantime, this is how we got to the place where the jQuery return object is "array-like" but not a true array.
A jQuery object is a wrapper around an array of DOM elements. So a "jQuery array" is a jQuery object.
Related
I have read the JQuery documentation, and while much attention is devoted to what you should pass the function, I don't see any information on what it actually returns.
In particular, does it always return an array, even if only one element is found? Does it return null when nothing is found? Where is this documented?
I understand that jquery methods can be applied to the return value, but what if I want to just use the return value directly?
From Rick Strahl's description:
The jQuery Object: The Wrapped Set:
Selectors return a jQuery object known
as the "wrapped set," which is an
array-like structure that contains all
the selected DOM elements. You can
iterate over the wrapped set like an
array or access individual elements
via the indexer ($(sel)[0] for
example). More importantly, you can
also apply jQuery functions against
all the selected elements.
About returning nothing:
Does it always return an array? Does it return null?
You always get the same thing back, whether or not it has any contents is the question. Typically you can check this by using .val() (e.g. $('.myElem').val())
It doesn't return an array, it returns a jQuery object. The jQuery object is what contains all the special jQuery methods.
It never returns null, or another type. If one element is found, the jQuery object will have only one child. If no elements are found, the jQuery object will be empty.
As another answerer mentioned, it always returns the jQuery object.
This object always contains an array of elements (even if it is an empty array, or an array with just one object).
If you'd like to use the returned object "directly", as in, as a plain element, you can do one of the following:
$('selector')[0] // element
$('selector').get(0) // element
$('selector').length // number of elements in the array
The jQuery function (i.e. "$") always returns a jQuery object in every instance.
From the jQuery documentation:
The jQuery object itself behaves much like an array; it has a length property and the elements in the object can be accessed by their numeric indices [0] to [length-1]. Note that a jQuery object is not actually a Javascript Array object, so it does not have all the methods of a true Array object such as join().
The fact that $() always returns the jQuery function lets you chain jQuery function calls judiciously.
Jquery selector mechnism
$("..") , the jquery selector, is used to select matched elements.
Return value
It always return an array-like jquery object, which has a length property,
Call method on returned jquery object
Methods of jquery could be called on the object, and apply to those selected elements,
Access original element by index
The selected elements, are store as property of the object, their property name are index numbers start from 0,
thus could be accessed by index, start from 0,
after get the original element, you can treat it as if get by document.getElementXxx().
Wrap an original element to a jquery object
After get the original element, you can wrap it to be a jquery object, by calling $(originalEle),
then you can call jquery methods on the wrapped object.
According to firebug, it returns an array of objects that match to your selector. But this array is a jQuery object, that more methods than a simple Array.
Their documentation lists a few of the core calls you can use with "$" and what they return
This is not actually a jQuery question, but jQuery does something I would like to be able to do with other objects.
I notice that jQuery returns the number of elements using the .length property. However, the jQuery object is not actually an array, so the number of elements is not naturally available that way.
I presume that the jQuery object uses numbered keys for the actual elements, since [n] returns one of them.
How is it possible to have a .length property of a non-array automatically updated when elements are added or removed? Or is that manually maintained when jQuery adds or removes elements?
Thanks
As you've observed, a jQuery object is not actually an array. Thus, the .length property is just maintained manually by any method that might actually change the internal contents of the array-like list of DOM objects.
This works fairly easily with a jQuery object because very few methods actually change the list of DOM objects in an existing jQuery object. Most jQuery methods such as .filter() that operate on the list of DOM element in a jQuery object actually return a new jQuery object and the original jQuery object is not modified.
Even a jQuery method like .add() or .slice() do not modify the existing jQuery object, but instead return a new jQuery object with the appropriate modification in it.
If you trace through the jQuery source and look at how a lot of jQuery objects are created, pretty much all the methods that operate on a given jQuery object go through .pushStack() which calls jQuery.merge() which manually sets the .length property on the new jQuery object.
If you look at the code for the main jQuery constructor $(someSelector), it does some sort of document query, builds the internal array-like list of DOM nodes, then manually sets the .length property.
It’s manually maintained. Compare:
var l = [];
console.log(l.length); // 0
l[0] = 0;
console.log(l.length); // 1
var l = $([]);
console.log(l.length); // 0
l[0] = 0;
console.log(l.length); // 0
One of my friends uses [].slice.call() to fill an array with matched elements.
I wonder how this works. I just know the Array.prototype.push to fill an array.
Also I have seen there is a difference in both techniques to fill an array.
So my questions are:
How does Array.prototype.slice help to fill an array?
What are the roles of Array.prototype.slice and Array.prototype.push to make objects and arrays?
Fiddle
var arr=[];
var arr=[].slice.call($('[id^=name]'));
//arr.push($('[id^=name]'))
console.log(arr)
The .slice() method of arrays returns a shallow copy of a portion of an array. It's written as a method on the Array prototype, so the array it operates on is the array in whose context it's invoked. Normally that'd be something like this:
var newArray = oldArray.slice(2, 4);
When you call the .slice() method with .call(), you can control the value of this explicitly. In your friend's code, he's passing a jQuery object as the this value. Because there are no other parameters, .slice() returns a shallow copy of the jQuery object in its entirety, as a new array. (Like some other similar methods, .slice() will work on anything that looks like an array: basically, anything that has a .length property and numerically-indexed properties of interest. A jQuery object fits that description.)
However, since jQuery already has a built-in method to return a plain array of all matched elements, your friend should not bother doing that anymore:
var plainArray = $('[id^=name]').get();
That does exactly the same thing. Using .slice() isn't wrong, but it's kind-of pointless.
How about $('[id^=name]').get()?
The [].slice.call method leverages the array-like length and numeric key properties of jQuery objects to re-use the intentionally generic methods of Array.prototype. The method Array.prototype.slice is documented by the standard to return a new Array object by performing a specific algorithm that accesses numeric-keyed properties in sequence of the this object - regardless of its type - assigning the values to sequential elements of the new Array.
I wouldn't use either approach, because jQuery has get(), which is documented to return an array of the elements matched. Why use a more obscure or less direct approach?
I does't have any specified reason for this case, but The thing i know is, .slice() also used to create another instance of an array, And here the slice add a space to its instance because it have no parameters.
Javascript is the language where you perform a Single operations in 1000's of different ways ! its depend on your choice!
But, We must have to follow the syntax that is made for particular operation.
This question already has answers here:
Why is it possible to query jQuery('div') like an array?
(5 answers)
Closed 9 years ago.
Just like $ itself is not simply a user defined object (it is, at its base, a function and that is why you can use the () operator on it and it inherits all the functions from Function.prototype) what is the actual Javascript type of the so-called jQuery object?
It has to be one of the standard array-like objects because you can use the [] operator on it, something you can't even do on strings in IE8 (and no, you can't, not on the Object String. You can on string literals before they're boxed).
So again, its not a user defined object (NB there's no such thing as a jQuery object, its written in raw javascript somewhere along the line). I have a feeling its a NodeList (or equivalent in browsers that don't have NodeList).
A reason you might have noticed this is you've added methods to the Array prototype, and you discover the function doesn't exist on a set of nodes found by jQuery!
So is anyone intimate with jQuery enough to share this lower level info with me? Or is there a short, exhaustive list of array-like objects in Javascript that I can test the jQuery object against till I find out which one it is myself?
The reason I ask this, instead of assume that jQuery is just adding elements to the object, using indexes as property names (I.e. obj[0] = x;) is because of how the Chrome dev tools and Firebug display them.
This shows dev tools displaying Array, jQuery and Array-like objects, and that there is at least some magic behind what jQuery is doing.
EDIT
It's not a NodeList. If it helps; inspecting it in Chrome shows that it is of type jQuery.fn.jQuery.init[0] with a __proto__ describing itself as Object[0] (which has all the jquery methods). Anyone explaining what and how jQuery is doing would be greatly thanked. I'm going to look at jQuery's source now.
And as for the image, it isn't simply an overridden .toString().
$('').toString == Object.prototype.toString //true
$('').toString == Array.prototype.toString //false
What is a jQuery object?
The $() or jQuery() function returns a jQuery object. It is not an Array and not a NodeList, and not in any way derived from either of those. It is an Object created with the jQuery constructor (which is actually the jQuery.fn.init() function). This object is very much like any other Object created with new SomeConstructor(), or even a plain object literal.
When you call $() or jQuery() without a new operator, it automatically does a new for you:
jQuery = function( selector, context ) {
// The jQuery object is actually just the init
// constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
The jQuery object is somewhat "array-like" in that it has properties with numeric indexes and a .length property, but these are just properties set directly in the object in the jQuery code. It also has a number of properties and methods that come from its prototype, which is jQuery.fn or jQuery.prototype (jQuery.fn is merely a reference to jQuery.prototype; they are the same object.)
You can see an example of this in the jQuery code that wraps a DOM element when you use $(element):
// HANDLE: $(DOMElement)
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
} ...
In this bit of code, selector is actually a DOM element, and the code stores that element in this[0] and sets this.length to 1. This is why you can use [0] and .length, simply because the object has these properties that were explicitly set.
Why does a jQuery object display like an Array?
There is some magic involved here, but the magic is in Firebug and the Chrome Developer Tools. They both look for two specific properties to decide to display an object as if it were an array:
A length property which is either a number or a string containing a number.
A splice property which is a function.
If the object has both those properties, it is displayed as an array.
You can test this by pasting the following line into either the Chrome DevTools or Firebug:
({ splice:function(){}, length:0 })
Chrome displays:
[]
Firebug displays:
Object[ ]
Remove either property and it will display as an object.
It doesn't matter if these properties are in the object itself or its prototype. You can paste this code into either console and it will display the same array-like notation as the code above:
function A(){}; A.prototype = { splice:function(){}, length:0 }; new A;
You can add an element to your "array":
({ splice:function(){}, length:1, 0:'test' })
Now Chrome displays:
["test"]
and Firebug displays:
Object[ "test" ]
Note that the Firebug display is not exactly the same as what it displays for an actual Array. Firebug puts that Object prefix in front of the array-like display to let you know that it's not an actual Array.
It does that on jQuery objects too. If you enter:
$(document.body)
Firebug displays:
Object[ body ]
You can click the word Object to get the full object-style display of the jQuery object instead of the array-like display.
Chrome doesn't make this distinction; it displays an Array or an array-like Object the same way.
So there's the magic. It's really nothing special in jQuery, except that the object it returns does have the length and splice properties. The splice() method is on the prototype and the length property may come from the prototype (for an empty "array") or more often from the jQuery object itself.
Those two properties trigger the real magic: a hack in the DevTools and Firebug to try to provide a more useful display for objects like these.
Bragging rights :-)
A bit of historical trivia: I was actually responsible for this part of jQuery's architecture. The very first version of jQuery in early 2006 didn't work like this. The jQuery object didn't have a .length and [0], [1], etc. properties. Instead it had a "private" array of its own, and you had to use .get(n) to fetch values from that array.
I thought it would be more convenient to have direct array-like access to the elements and came up with the idea of setting the .length, [0], [1], etc. properties so it would work like a read-only array.
my understanding is a sub class of Array, which inherited from Array Class and has its own method
changes above:
it's not sub class of Array. But it made from Array, but after Array object created, jQuery alter the object prototype with jQuery its own prototype,then finally it become jQuery object which is Array-like object.
var username = $("#username"),
password = $("#password"),
allFields = $([]).add(username).add(password);
What is allFields? What is $([])?
Being a newbie to Javascript/jQuery, I've never seen this $([]) notation before and I'm interested in its associated methods.
Given that its "$([])", it's tricky to search for. And a Google search of arrays in Javascript (guessing that thing is an array of some sort) yields the typical arrays I'm familiar seeing.
So what is $([])? Can anyone point me to some documentation? I'm interested in learning how to use this strange thing.
The jQuery function accepts an array of DOM nodes.
$([document.body]) for example which will return a jQuery object by wrapping all the DOM elements passed in that array. However, since in your example there is no DOM object to begin with and it's just an empty array, there is not need to even pass an empty array.
Calling the jQuery function without any arguments returns an empty set. Taken from jQuery docs,
Returning an Empty Set
As of jQuery 1.4, calling the jQuery() method with no arguments returns an empty jQuery set. In previous versions of jQuery, this would return a set containing the document node.
So, your example would work the same if you had instead called
$().add(username).add(password);
As other answers have mentioned and the docs say, passing an empty array was required before v 1.4.
[] it's an empty array. Wrapping it with $() overcharges it with jQuery's functions.
In javascript you can create an array this way:
var foo = [];
It is an empty array being passed in the creation of a jQuery object. Presumably to initialize something.
Shouldn't be necessary, at least not in the latest versions of jQuery.
Here's an example without the Array: http://jsfiddle.net/MAzLN/
Works fine, as the alert() shows one element in the object.
jQuery initializes the length property to 0 when the object is created, so I'm not sure what the purpose is, unless it was required in the past.
I believe it creates an empty jQuery collection object.