What does jQuery .find() method return? a object OR a array list of objects?
If it returns an object which contain all the matched elements. How to convert this object to an array?
If it returns a array of elements, why $(xml).find("DATE").sort(mySortFunc); does not work, it seems the jQuery .find() returns an object which can not apply Javascript sort() method which is supposed to be applied on array.
Generally, I need to sort the objects find by $(xml).find("DATE") , but when I use sort function, it raised an error that the object can not be resolved.
The majority of jQuery methods returns a jQuery object, which can be accessed like it is an array (e.g. it has a .length attribute, elements can be accessed using the square bracket notation ([0]), and it supports some array methods (slice())).
jQuery has a method called toArray() which can be used to convert the jQuery object to a real array.
You can also use get() with no arguments to achieve the same effect (and save you a few key presses).
In future, you can checkout the jQuery API, and the return type for all jQuery methods is listed in the relevant documentation (e.g. for find(), the return type is "jQuery")
If you call .get() on a jQuery object without a parameter, it will return a regular array of DOM elements.
jQuery already acts like an array, and thus you can apply array like functionality to it.
Try to change
$(xml).find("DATE").sort(mySortFunc);
with
Array.prototype.sort.apply($(xml).find("DATE"), mySortFunc);
and you should get what you need
Related
Long time I write code in JavaScript, using jQuery, ReactJS and NodeJS server side (ExpressJS). I learned partially MDN and other sources, however there is one question I can not found an answer for.
Why follow code requires prototype object's property? Why I can not use forEach directly from Array object? I mean, in terms of OOP, if Array class extends class contains forEach method, I can call it from object instantiated from Array directly, I don't need, using reflection find base class, instantiate it and call the method from the base class.
Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
el.addEventListener('click', someFunction);
});
Example taken from here: https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/
Your code:
Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
el.addEventListener('click', someFunction);
});
could indeed be written as
[].forEach.call(document.querySelectorAll('.klasses'), function(el){
el.addEventListener('click', someFunction);
});
Going through the Array prototype object is just a way to access the functions available to any array instance without having to actually create an array. Using one or the other is mostly a matter of preference, and though the second form does involve the creation of an array object, the performance implications are minimal.
Why I can not use forEach directly from Array object?
The Array object is a constructor function used to create arrays. It doesn't have a forEach property of its own.
You can access the forEach property either from an instance of Array (which you can create with new Array or, more idiomatically, with []), or by accessing the prototype that gets applied to instances of Array.
querySelectorAll doesn't return an Array, returns a NodeList (like array-object) instead. The NodeList has a property called .length that indicates the count of elements inside of it.
Some browsers/engines/backend techs are incompatible because that NodeList no necessarally will provide the function forEach.
So, an alternative is converting that NodeList to an Array using the Array prototype:
Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){...})
Or, you can use the function Array.from that will use the property .length to create the array:
Array.from(document.querySelectorAll('.klasses'));
From MDN docs
Although NodeList is not an Array, it is possible to iterate on it using forEach(). Several older browsers have not implemented this method yet. You can also convert it to an Array using Array.from.
When accessing an array, when is it appropriate to use the .eq() function?
For example, I have...
slides.eq(slidesLength-1).css("z-index", (slidesLength-1));
and later I have...
for(i=0; i<slidesLength-1; i++) {
$(slides[i]).css("left", "-100%");
}
In the first piece of code, the slideshow stops functioning if I don's use the .eq() function. However, the second piece seems to function whether I use the .eq() function or not. Why is this?
slides is not an array. It's a jQuery object. The .eq() method returns you the element at the specified index as a jQuery object.
While jQuery objects may not be arrays, they can pretend to be by having a length property as well as properties corresponding to the indexes. (Since they are not arrays, you can't call methods like .pop(), .forEach(), etc. on them.)
When you do slides[i], you are actually getting the DOM element, not a jQuery object. The $() function turns the DOM element into a jQuery object.
So, when you do slides.eq(1), internally jQuery is doing $(slides[i]).
P.S. Objects, like jQuery objects, that pretend to be arrays are called "array-like objects". If you console.log(slides), it may look like an array. This is just your console trying to make things convenient for you. (See this question for more info: Creating array-like objects in JavaScript)
.eq() is a jQuery method which returns a jQuery object, while accessing by index returns plain DOM element. You should use eq() when you want to use jQuery methods (css() in this case) on the returned selection.
The reason $(slides[i]) works is because you're constructing a jQuery object by passing the plain element to $() constructor.
Your slides variable is not an Array, but a jQuery object.
.eq() returns a jQuery object, eventually empty if index is out of bounds, and a negative index is counted from the end.
.get() returns a DOM Element, or undefined if index is out of bounds, and a negative index is counted from the end.
[] returns a DOM Element, or throw an Error if index is out of bounds.
...
Additionally, jQuery methods let you interact with a set of elements as it was alone. So you if you do:
slides.css("left", "-100%");
It is applied on every matched elements contained in the jQuery object. It is unnecessary to loop over them.
...
Also the preferred way to loop over matched elements is using the each() method:
slides.each(function (i, el) {
var $el = $(el);
});
...
Also it is an established convention to prefix jQuery variables with a $ sign; it let you to easily differentiate DOM elements from jQuery objects. But that's only a matter of taste.
Is there a way to have get() returning a jQuery object instead of "just" the DOM element?
Example:
$("div").get(0) returns [<div></div>] instad of <div></div>.
I'd like to prevent overwrapping like $($("div).get(0)) because the query will get a little bit longer than the example and I fear the readability gets lost. I'd rather not use variables to save unnecessary DOM elements in the RAM, either.
Use eq() to return the jquery object instead of get()
$("div").eq(0)
Given a jQuery object that represents a set of DOM elements, the .eq()
method constructs a new jQuery object from one element within that
set. The supplied index identifies the position of this element in the
set, jQuery doc
You would use eq:
$("div").eq(0)
Use eq() instead , which will return jQuery object
$("div").eq(0)
Also try this also:
$('div:first')
I don't understand how this works:
var links = [].slice.apply(document.getElementsByTagName('a'));
It creates an empty array but I don't completely get the rest. What do slice and apply really do together in this script?
document.getElementsByTagName() and similar DOM methods return an array-like structure, a node list, instead of a true array. This is a common trick to convert it into a true array. It is also commonly used with the arguments special variable, another array-like structure. The slice method of the Array object would normally expect an array, and returns an array, but this way you can pass in something that is not technically an array. A slightly more readable, and arguably better version is this:
Array.prototype.slice.apply(document.getElementsByTagName('a'));
This basically converts the nodeList object retrieved from the getElementsByTagName into regular javascript array, to be able to use array methods on it.
I'm having trouble with jquery and selectors using the following code:
<div id="test"></div>
console.log($('#test'));
This always returns a list like [<div id="test"></div>] instead of the single element.
This results on always having to write $('#test')[0] for every operations instead of only $('#test'). Any idea on why?
Regards
Jquery will not return the HtmlElement, it returns a jQuery object.
A jQuery object contains a collection
of Document Object Model (DOM)
elements that have been created from
an HTML string or selected from a
document. Since jQuery methods often
use CSS selectors to match elements
from a document, the set of elements
in a jQuery object is often called a
set of "matched elements" or "selected
elements"
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().
http://api.jquery.com/Types/#jQuery
This is an example of the Composite Design Pattern
The Composite Pattern describes a group of objects that can be treated in the same way a single instance of an object can. Implementing this pattern allows you to treat both individual objects and compositions in a uniform manner. In jQuery, when we're accessing or performing actions on a single DOM element or a group of DOM elements, we can treat both in a uniform manner. http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjquery
jQuery encapsulates any objects found for a number of reasons. For one, it ensures that no matter what, null will never be returned for example. Rather, the elements found are inserted into a list. The fact that even though you're searching for a single element, the mechanism always remains the same and therefore the results will be placed into an array of one element rather than the element itself.
In jQuery it is better to think of selectors as matching multiple items, and your solution would be best if you use the each syntax to iterate through the matches items...
$('#test').each(function() {
console.log($(this));
});
As ID is not unique, jQuery looks for every element with such ID. So it's always returns a list, because threre is no guarantee that the element is exactly one