I decided to write an article that will be useful for beginners to understand their mistakes and to put together some practices.
Of course, the number of such examples is very, very large, so I will limit myself to just a few.
This problem concerns not only javascript, but programming in general. Consider an example:
$elem.on('keydown', function(e) {if (e.keyCode == 27) {//... }});
What is the magic number 27? People who code often will notice — this is the ESC key. But most developers, especially beginners, either do not remember these codes, or do not know at all, and when faced with codes, they are forced to climb once again into the search system and waste time.Of course you can add a comment in the code but it would be much more efficient to enter a constant, for example: KEY_ESC = 27
Often we need to get the identifier of an element (comment, post, user, etc.) in order to perform some actions (for example, evaluate the comment using ajax) and often you can find this approach:
var id = $(this).attr('id').substring(8);
As in the previous example, the developer has to guess — what is this number 8.
Another example (this line is copied from a real project):
var last_id = $('#answer_pid' + id + ' li:first div').attr('id').substr(7);
The slightest change in the html layout will brake the code.
Okay, there is another:
<div class="comment" id="comment_123"></div>
var id = $(this).attr('id').substring("comment_".length);
This is better (at least there are no wired numbers), but still this approach too much binds the js code to html.
We can use the “data-*” parameters:
<div class="comment" data-id="123"></div>
It much more easier to get the identifier now:
var id = $(this).attr('data-id');
or
var id = $(this).data('id');
We all know a jQuery method for working with ajax — $ .ajax. There are several shorthand functions such as $ .get, $ .load, $ .post, etc.
These functions have been added specifically to facilitate frequently performed actions (upload a script, json, execute a post request), but in the implementation all these methods refer to $ .ajax.
Personally, I never use shorthand functions, and that’s why.
In beginners or inexperienced code you can find several different stages:
a. Starting
$.post(url, data, function(data) {data = $.parseJSON(data);_//..._});
b. Adding the “try-catch” block
$.post(url, data, function(data) {try {data = $.parseJSON(data);} catch (e) {return;}//...});
c. We learn from the documentation that in $ .post the last parameter can be passed to the dataType (which disappears in tons of code if success function doesn’t fit into the screen).
$.post(url, data, function(data) {_//..._}, 'json');
I rarely can see error handlers in beginners projects, this is mainly due to laziness and unwillingness to spend extra 5 minutes of time, or the developers are just sure that there will be no errors.
If the developer decided to add an error handler to $ .post, it often be something like:
$.post(url, data, function(data) {_//..._}, 'json').error(function() {//...});
Which is really unreadable. Writing an error handler every time is a tedious task, so you can set up a default error handler for all ajax requests, for example:
$.ajaxSetup({error: function() {// Error modal }});
Let’s return to $ .post. As shown above, using $ .post makes the code looks awful (especially with the dataType in an incomprehensible place). Lets rewrite the last example in $ .ajax.
In my opinion, this approach is more readable and easier to maintain.
$.ajax({type: "POST",url: url,data: data,dataType: "json",success: function(data) {//...},error: function() {//... }});
Sometimes is necessary to add event handlers to page elements (for example, the “delete message” button). And often you can come across this approach:
$('.comment a.delete').click(function(){_//..._});
Now the problem is to add the same handler to a new element (for example, to a dynamically loaded comment). I saw a lot of solutions, including redefining all the handlers once again:
$('.comment a.delete').unbind('click').click(function() {_//_});
There is a method in jQuery 1.7 called “on”, which binds the event handlers, filtering the elements by the selector.
$('body').on('click', 'a.external', function(e) {// The function will be called when you click on any link with the external class});
Important to remember, that this handler works for dynamically created objects too. This approach should be applied wisely. For example, the following code can lead to performance degradation and slowdown of the browser:
$('body').on('mousemove', selector, function() {_//..._});
The fact that namespaced events were added to jQuery 1.2 — they are few people use it (I think most people just don’t know about them).
For example, we have this code:
$('a').on('click', function() {_// Handler 1_});
$('a').on('click', function() {_// Handler 2_});
Now, for example, we need to remove the second handler from the links. But $(‘a’).off(‘click’) will remove both handlers.
Lets use namespaced events:
$('a').on('click.namespace1', function() {_//Handler 1_});$('a').on('click.namespace2', function() {_//Handler 2_});
Now it becomes possible to remove the second handler by calling
$('a').off('click.namespace2');
More information about namespaced events can be found here.
This is only a small part of the problems that I regularly encounter in someone else’s code. I hope that this post will help improve the quality of the code.