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
Related
Why (if at all) should I avoid doing this:
if (NodeList.prototype.map === undefined) {
NodeList.prototype.map = Array.prototype.map
}
or anything else from here (I am not referring to []., I know it's slow)
As far as I know, this behavior was popular in the Prototype 1.0 and Mootools era, and was used with reckless abandon, only to quickly be depreciated because of inconsistencies between browsers.
Seems to work fine now, especially for such a conservative use. Should we still steer clear?
Because, in the event that NodeList ever gets a standard map method, it would conflict with yours.
Even if you check whether a current method exists, for example by checking to see if the prototype holds undefined before assigning a replacement, the people who write web standards have to make sure that their changes don't break our (meaning web authors') working code. Backwards compatibility is one of the core principles of the open web; we trust that if we write code today and leave it for a week or even a few years, it should still work.
Prototype and Mootools became problematic for this very reason; they were incredibly popular and they didn't hesitate to modify the prototypes of built-ins as they saw fit.
Ever wonder why .contains() is instead named the less familiar .includes() on both strings and arrays? Oh, yeah, that was because Mootools had already defined .contains() and the new standard ended up breaking a significant number of existing web pages by defining an inconsistent implementation.
TL;DR: It probably doesn't matter for any single page, but it can become a big issue when used by a popular library so people tend to avoid the practice altogether.
I have developed a Javascript library which requires the bind method.
Unfortunately, bind is not supported by IE8.
There are a polyfill on the MDN website which work well.
My question is:
Are there problems or possible incompatibility between this polyfill and other Javascript libraries ?
It is safe to use in any case?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
For me most obvious differences with native bind are:
arguments.caller does not point to the caller of bound function, but you shouldn't use it anyway
length of bound function is set to 0, this may affect function arity checks like https://github.com/fitzgen/wu.js/blob/master/lib/wu.js#L406
IMHO if you are using only "the good parts" of JavaScript, and not developing core of some framework (for IE8?), you shouldn't face any problems with this polyfill.
The answer is pretty much there on the MDN page itself:
"If you choose to use this partial implementation, you must not rely on those cases where behavior deviates from ECMA-262, 5th edition! With some care, however (and perhaps with additional modification to suit specific needs), this partial implementation may be a reasonable bridge to the time when bind() is widely implemented according to the specification."
There's nothing wrong with the MDN shim as such. However if you choose to use their shim make sure that it can't be overridden by other libraries. I had an issue a while ago with Strophe doing just that and replacing one shim with another.
I tend to use underscore to cover stuff like this but there are other options like es5shim. With underscore you have a method called (you guessed it) '.bind' and works slightly differently to MDN's shim (uses 'new' invocation). Underscore also has a great method called '.partial' which can be useful in scenarios where you don't want to change the value of 'this' but partially apply arguments.
The point I am making here is that instead of shimming, maybe look at something that is properly protected/encapsulated within a library. The chances are you're going to need more than one shim in any case if you're targeting browsers like IE8.
Lastly, and not so importantly check out the performance tests at:
http://jsperf.com/browser-vs-es5-shim-vs-mdn-shim
jQuery is highly focused on the DOM and provides a nice abstraction around it. In doing so, it makes use of various well known design patterns which just hit me yesterday. One obvious example would be the Decorator pattern. The jQuery object provides new and additional functionality around a regular DOM object.
For example, the DOM has a native insertBefore method but there is no corresponding insertAfter method. There are various implementations available to fill this gap, and jQuery is one such library that provides this functionality:
$(selector).after(..)
$(selector).insertAfter(..)
There are many other examples of the Decorator pattern being heavily used in jQuery.
What other examples, big or small, of design patterns have you noticed that are part of the library itself? Also, please provide an example of the usage of the pattern.
Making this a community wiki as I believe that various things people love about jQuery can be traced back to well known design patterns, just that they are not commonly referred to by the pattern's name. There is no one answer to this question, but cataloging these patterns will provide a useful insight into the library itself.
Lazy Initialization:
$(document).ready(function(){
$('div.app').myPlugin();
});
Adapter or wrapper
$('div').css({
opacity: .1 // opacity in modern browsers, filter in IE.
});
Facade
// higher level interfaces (facades) for $.ajax();
$.getJSON();
$.get();
$.getScript();
$.post();
Observer
// jQuery utilizes it's own event system implementation on top of DOM events.
$('div').click(function(){})
$('div').trigger('click', function(){})
Iterator
$.each(function(){});
$('div').each(function(){});
Strategy
$('div').toggle(function(){}, function(){});
Proxy
$.proxy(function(){}, obj); // =oP
Builder
$('<div class="hello">world</div>');
Prototype
// this feels like cheating...
$.fn.plugin = function(){}
$('div').plugin();
Flyweight
// CONFIG is shared
$.fn.plugin = function(CONFIG){
CONFIG = $.extend({
content: 'Hello world!'
}, CONFIG);
this.html(CONFIG.content);
}
The Composite pattern is also very commonly used in jQuery. Having worked with other libraries, I can see how this pattern is not so obvious as it looks at first sight. The pattern basically says that,
a group of objects are to be treated in the same way as a single instance of an object.
For example, when dealing with a single DOM element or a group of DOM elements, both can be treated in a uniform manner.
$('#someDiv').addClass('green'); // a single DOM element
$('div').addClass('green'); // a collection of DOM elements
How about the Singleton/Module pattern, as discussed in this article about YUI: http://yuiblog.com/blog/2007/06/12/module-pattern/
I believe jQuery uses this pattern in its core, as well as encouraging plug-in developers to use the pattern. Using this pattern is a handy and efficient way of keeping the global namespace clear of clutter, which is further useful by assisting developers in writing clean, encapsulated code.
In the eyes of functional programming, jQuery is a Monad. A Monad is a structure that passes an object to an action, returns the modified object and passes it on to the next action. Like an assembly line.
The Wikipedia article covers the definition very well.
Would you consider extending the native elements via the prototype dangerous? I see some frameworks such as Prototype doing this so I have started to wonder if I dare to do that too.
I am worried about implementing things like addClassName and make it collide in the future in a way that I can't resolve any other way than rewriting the software and asking module authors to do the same.
I wouldn't because IMHO it might definitely make collisions soon or later and create a potential bug very difficult to be spot out.
I anyway do extend some basic simple native Javascript objects like String.trim, I'm anyway careful to always test to see if it already exists by using a simple if test:
if(!String.prototype.trim)
String.prototype.trim = function() { return this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }
You could do the same with addClassName.
The difference is that doing it with simple function like String.trim, it's difficult that might lead to problems in future, because even if a browser engine has got String.trim (actually FF has it) well such a function is going exactly to do what my String.trim does, so you won't see differences in your web application workflow ever.
A more complex function like overriding querySelectorAll might lead to differences between how the browser implements it and your implementation. For example: the order of the returned elements might be different, the browser function returns a collection while your one an array, and other issues. So when you run your webapp on browser that does implement the querySelectorAll it might lead to having your webapp not working anymore as expected, and there try finding out the bug!!!
Maybe querySelectorAll is not the best example, but I hope I explained the concept.
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.