I am quite new to javascript/jQuery, I wonder when and what function can be used interchangeably? Such as when to use src, or attr("src"), so on and so forth..
I use jQuery methods when I already have a jQuery object and the jQuery method implementation does something useful for me that the DOM method does not (such as operate on a whole collection or allow me to chain multiple operations together or provide functionality that the DOM method does not or provide some sort of cross browser support that might be an issue).
I use DOM methods when I have only a single DOM element and the DOM method or property does exactly what I want. Direct DOM operations that do exactly what you want are usually significantly faster than creating a jQuery object and then calling a similar method on the jQuery object. jQuery can be very useful and offers lots of useful functionality, but it isn't really helping you (and probably is slowing you down) if you're just doing something that a DOM property or method already offers built-in.
In the specific case you asked about, assuming you're talking about an image object, elem.src is not exactly the same thing as $(elem).attr('src').
elem.src will be a fully qualified URL whether the original src attribute was specified as fully qualified or not.
$(elem).attr('src') will be exactly what the src attribute was specified as. For example, it might be image01.jpg. It is more directly analogous to elem.getAttribute('src'), not to elem.src.
There is no general guideline for other properties that answers your broad and general question. One has to understand what the jQuery method does and how that compares to the DOM property or method and know when there is a meaningful difference. There is no substitute for learning each method/property so you know which one might best serve your purpose.
Related
I've been writing Javascript for years, but just now realized I don't entirely understand how these "HTML-y" methods actually interact with the DOM.
My assumption is that when HTML is interpreted into the DOM, the browser keeps references as to which HTML element became which DOM node.
So for .getElementById when you select an element, the browser returns the relevant node by reference. Why not just do .getNodeById then and be more correct?
My assumption is that .innerHTML is interpreted by the browser into the DOM at runtime. However, in older browsers like IE7, .innerHTML cannot be used to create table nodes. This suggests to me that it was originally intended just to modify the text properties of existing nodes, but then it seems strange that it exists at all, and we don't just use .innerText.
I guess I'm just confused by some Javascript history.
Well, the thing is, things like .innerHTML and .getElementById aren't really JavaScript objects at all. They're what the language specification calls "Host Objects" - it's a form of FFI. What happens when you call .getElementById in most browsers is that the string is marshalled from a JS string to a DOM string and then passed to C++ code.
In fact, they're allowed to have pretty much whatever semantics they please - the language makes no guarantees about how they act (this is also true for other DOM objects like timers and XHR).
well if you really want to know about the internals and want to digg into the deep rabbit hole of rendering engines i'd give you a start by pointing you to certain source files of chromium:
http://src.chromium.org/viewvc/blink/trunk/Source/core/dom/Element.cpp
you could find stuff like innerHTML and how it actually works in it. (around line 2425)
.getElementById() will just resolve to a document element that matches the specified id and will return a reference to it.
its some kind of identifier with prototyped methods, getters and setters to interact with that element. as soon as you interact with methods like innerHTML etc. you will simply tell the engine to execute that action on the element that is referenced inside the element reference.
just digg around inside the source code. you might get a good insight:
http://src.chromium.org/viewvc/blink/trunk/Source/core/dom/
I mostly call jQuery elements by the id of the DOM object using the $('#id') syntax. I think that this goes through the selector algorithm, and spends some time on that process.
I was wondering if there is a way to dig into that function and access jQuery objects from the id of the DOM in a more direct way (at the lower level) to improve performance. Will it worth doing so? If so, how can I do it?
If you want to improve performance, keep a jQuery object that's used for single node synchronous operations
var _id = $(document);
Then update its 0 property when you need to fetch by ID.
_id[0] = document.getElementById("id");
_id.css(...);
This eliminates the vast majority of its overhead. Because JS is single threaded, you can reuse this object wherever needed. But if you want to do some operation in a setTimeout(), you should probably just create a new object to be safe.
When you pass jQuery a single, lone ID selector, it automatically skips any selector processing and calls document.getElementById() directly. It's only when the selector string consists of anything more than an ID selector that it always treats it like a selector (this includes selectors like div#id, .class#id, or even #wrapper #id).
In most cases, this is something you don't have to worry about, since jQuery already does a lot of optimization for you. But if you're paranoid and want to remove every hair and every ounce of any possible overhead, see cookie monster's answer.
Going native will always be faster / more direct:
var id = document.getElementById("id");
But you will loose the benefits of wrapping your object in a jQuery wrapper.
You can also do :
$(document.getElementById("id"))
That way you are passing in the direct object rather than performing a lookup on the dom.
You want to use getElementById like this
var name = document.getElementById('id');
Actually.... this will depend on the browser u will be using to run the script.... here i did some dig on the internet..... i found a test result on this topic.....
Here is the Site
As to them JQuery selectors are faster than the native JS code.
Which jQuery methods should be avoided in favour of built-in methods / properties?
Example:
$('#el').each(function(){
// this.id vs $(this).attr('id');
// this.checked vs $(this).is(':checked');
});;
I use the direct javascript property like this.id in these cases:
Whenever it does exactly what I want.
When speed is important.
When all browsers I care about support exactly what I need.
I use the jQuery access method when:
There are cross browser support issues or I'm not sure that there aren't cross browser issues.
When the jQuery way has more or enhanced functionality that is useful in my circumstance.
When it's part of a chained operation and chaining works better with jQuery.
When I'm already using jQuery for this operation and it seems inconsistent to mix/match some direct access and some jQuery access.
For example: str = $(elem).html() doesn't really have any advantages over str = elem.innerHTML, but $(elem).html(str) does have some advantages over elem.innerHTML = str; because the jQuery method will clean up the objects that are being removed more completely than the innerHTML way.
This is a broad question but here's a couple of guidelines that I think are useful.
You can/should use native js methods when:
You know what you are doing. That is you know the spec and any possible inconsistencies between browsers.
You are writing performance-critical piece of code where convenience is not top priority
You are not satisfied with the way library function works. This can break down to the following:
library implementation is buggy (that happens)
library implementation is incomplete (e.g. doesn't yet support some new features that are OK to use in your case)
simply your vision of some feature is different from library's implementation
The first condition should be true in any case :) The others can combine or go separately. I understand that they are all debatable and can provoke long talks on philosophy but I think they are good starting points and summarize lots of cases.
But the bottom line is - if you don't have a reason to avoid library methods, use them!
Most DOM properties are problem-free in all major browsers. For the two examples you mention (id and checked), the DOM properties are 100% reliable and should be used in preference to the jQuery equivalent for reliability, performance and readability.
The same goes for all properties corresponding to boolean attributes: readonly, disabled, selected are common ones. Here are some more. className is also 100% solid. For other properties and attributes, it's up to you. Using a library like jQuery may be the best approach for these if you're unsure and can afford to lose some performance (usually the case).
Stack Overflow regular Andy Earnshaw has blogged about this: http://whattheheadsaid.com/2010/10/utilizing-the-awesome-power-of-jquery-to-access-properties-of-an-element
I need to know which of these two JavaScript frameworks is better for client-side dynamic content modification for known DOM elements (by id), in terms of performance, memory usage, etc.:
Prototype's $('id').update(content)
jQuery's jQuery('#id').html(content)
EDIT: My real concerns are clarified at the end of the question.
BTW, both libraries coexist with no conflict in my app, because I'm using RichFaces for JSF development, that's why I can use "jQuery" instead of "$".
I have at least 20 updatable areas in my page, and for each one I prepare content (tables, option lists, etc.), based on some user-defined client-side criteria filtering or some AJAX event, etc., like this:
var html = [];
int idx = 0;
...
html[idx++] = '<tr><td class="cell"><span class="link" title="View" onclick="myFunction(';
html[idx++] = param;
html[idx++] = ')"></span>';
html[idx++] = someText;
html[idx++] = '</td></tr>';
...
So here comes the question, which is better to use:
// Prototype's
$('myId').update(html.join(''));
// or jQuery's
jQuery('#myId').html(html.join(''));
Other needed functions are hide() and show(), which are present in both frameworks. Which is better? Also I'm needing to enable/disable form controls, and to read/set their values.
Note that I know my updatable area's id (I don't need CSS selectors at this point). And I must tell that I'm saving these queried objects in some data structure for later use, so they are requested just once when the page is rendered, like this:
MyData = {div1:jQuery('#id1'), div2:$('id2'), ...};
...
div1.update('content 1');
div2.html('content 2');
So, which is the best practice?
EDIT: Clarifying, I'm mostly concerned about:
Memory usage by these saved objects (it seems to me that jQuery objects add too much overhead), while OTOH my DOM elements are already modified by Prototype's extensions (loaded by default by Richfaces).
Performance (time) and memory leakage (garbage collection for replaced elements?) when updating the DOM. From the source code, I could see that Prototype replaces the innerHTML and does something with inline scripts. jQuery seems to free memory when calling "empty()" before replacing content.
Please correct me if needed...
You're better off going with jQuery. Both frameworks are great (and I use them both), but in your case jQuery is probably the winner.
In my opinion prototype provides a more natural syntax for javascript development. It does this at the cost of adding methods to some of the core classes, but it's also motivated by ruby where this is the norm.
jQuery on the other hand is far superior at dom manipulation and event observation. Your code will be more concise and manageable in these cases and will benefit from great performance features like event delegation. jQuery also has a much larger community and way more plugins and code samples.
If you're only interested in the three basic methods "update", "hide" and "show" then jQuery is better suited. It is aimed more at DOM manipulation which is exactly what you need. Then again you could do each of those things in a couple of lines of code, saving the 26KB needed to transfer the jQuery library.
Since your worry is in memory usage look at the jQuery file, it is 77KB uncompressed, how much work do you suppose that is for the browser to execute? Probably much more than that freed by calling empty() on a typical DIV.
And you mention Prototype is already in use on the site in which case you shouldn't be adding another library. jQuery's abilities are a subset of Prototype's.
This question is nearly a year old so you've probably made your decision by now. For anyone else reading the answer is simple; If something's not broken don't fix it, you already have one capable library installed so use that.
I would go for jQuery. Prototype used to modify default JS objects, which is fine but it means you have to be careful. I believe this is no longer the case though. JQuery also has a large plugin repository and the jquery UI extension for widgets. Btw. With JQuery you can use the familiar dollar sign as well.
I've been looking for a straight answer for this (I can think of lots of possiblities, but I'd like to know the true reason):
jQuery provides a .data() method for associating data with DOM Element objects. What makes this necessary? Is there a problem adding properties (or methods) directly to DOM Element Objects? What is it?
Is there a problem adding properties (or methods) directly to DOM Element Objects?
Potentially.
There is no web standard that says you can add arbitrary properties to DOM nodes. They are ‘host objects’ with browser-specific implementations, not ‘native JavaScript objects’ which according to ECMA-262 you can do what you like with. Other host objects will not allow you to add arbitrary properties.
In reality since the earliest browsers did allow you to do it, it's a de facto standard that you can anyway... unless you deliberately tell IE to disallow it by setting document.expando= false. You probably wouldn't do that yourself, but if you're writing a script to be deployed elsewhere it might concern you.
There is a practical problem with arbitrary-properties in that you don't really know that the arbitrary name you have chosen doesn't have an existing meaning in some browser you haven't tested yet, or in a future version of a browser or standard that doesn't exist yet. Add a property element.sausage= true, and you can't be sure that no browser anywhere in space and time will use that as a signal to engage the exciting DOM Sausage Make The Browser Crash feature. So if you do add an arbitrary property, make sure to give it an unlikely name, for example element._mylibraryname_sausage= true. This also helps prevent namespace conflicts with other script components that might add arbitrary properties.
There is a further problem in IE in that properties you add are incorrectly treated as attributes. If you serialise the element with innerHTML you'll get an unexpected attribute in the output, eg. <p _mylibraryname_sausage="true">. Should you then assign that HTML string to another element, you'll get a property in the new element, potentially confusing your script.
(Note this only happens for properties whose values are simple types; Objects, Arrays and Functions do not show up in serialised HTML. I wish jQuery knew about this, because the way it works around it to implement the data method is absolutely terrible, results in bugs, and slows down many simple DOM operations.)
I think you can add all the properties you want, as long as you only have to use them yourself and the property is not a method or some object containing methods. What's wrong with that is that methods can create memory leaks in browsers. Especially when you use closures in such methods, the browser may not be able to complete garbage cleaning which causing scattered peaces of memory to stay occupied.
This link explains it nicely.
here you'll find a description of several common memory leak patterns
It has to do with the fact that DOM in IE is not managed by JScript, which makes it completely different environment to access. This leads to the memory leaks http://www.crockford.com/javascript/memory/leak.html. Another reason is that, when people use innerHTML to copy nodes, all those added properties are not transfered.