Javascript and jQuery bikes

Once again opening the code of colleagues and horrified, I decided to write this article. I hope it will be useful to someone, at the same time, and it will be easier for me to beginners to explain what is wrong with their code, just by throwing a link to this article.
Of course, the number of such things is very, very large, so in the article I will limit myself to only a few.

1. Constants in the code


This problem concerns not only javascript, but programming as a whole. Рассмотрим example:
$elem.on('keydown', function(e) {
    if (e.keyCode == 27) {
        //...
    }
});

What is the magic number 27? People who often encounter codes will immediately say - 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 once again climb into the search engine and waste time.
You can of course add a comment in the code that this is ESC keypress processing, but it would be much more efficient to enter a constant, for example, KEY_ESC = 27

2. Obtaining identifiers


Often there is a need to get the identifier of an element (comment, post, user, etc.) in order to perform any action. (e.g. rate a comment using ajax). And often you can find a similar approach:

var id = $(this).attr('id').substring(8);

As in the previous example, the developer has to guess - what is this number 8. Climb into the html code, etc.
There are examples and worse (the line is copied from a real project):

var last_id = $('#answer_pid' + id + ' li:first div').attr('id').substr(7);

The slightest change in layout will cause js code to be edited.

Sometimes it happens:
<div class="comment" id="comment_123"></div>

var id = $(this).attr('id').substring("comment_".length);

It’s already better (at least there are no stitched numbers), but still this approach ties the js code too much to html.

In my opinion it is much better to use data- * parameters, for example
<div class="comment" data-id="123"></div>

then getting the identifier will be very simple:
var id = $(this).attr('data-id');

or
var id = $(this).data('id');

(There are many articles about the differences between attr and data)

3. $ .post


As you know - in jquery there is a method for working with ajax - $ .ajax. There are several shorthand functions to it, such as $ .get, $ .load, $ .post, etc. These functions were specially added to facilitate frequently performed actions (load script, json, execute post request), but in the implementation all these methods refer to $ .ajax.
Personally, I never use shorthand functions, and here's why:
In the code for beginners or inexperienced developers, there are several different stages:
1. Initial
$.post(url, data, function(data) {
            data = $.parseJSON(data);
            //...
});

2. A try catch block is added.
$.post(url, data, function(data) {
	    try {
                data = $.parseJSON(data);
            } catch (e) {
                return;
            }
            //...
});

3. We learn from the documentation that in $ .post, the last parameter can be passed dataType (which disappears in the abyss of code if the success function does not fit into the screen).

$.post(url, data, function(data) {
    //...
}, 'json');


Very rarely, web developers add error handlers. This is mainly due to laziness, or unwillingness to spend the extra 5 minutes of time, or the developers are simply sure that there will never be errors.
If the developer decided to add an error handler to $ .post, it turns out something like:
$.post(url, data, function(data) {
    //...
}, 'json').error(function() {
   ///
});


In my opinion, this is terribly unreadable. Да и писать каждый раз обработчик ошибок — дело нудное, поэтому можно настроить обработчик ошибок по умолчанию для всех ajax запросов, на example:

$.ajaxSetup({
    error: function() {
        //Показать окошко о том, что произошла ошибка
    }
});


Back to $ .post. As shown above - using $ .post makes the code horrible (especially with dataType in an incomprehensible place). We rewrite the last example on $ .ajax. In my opinion, this approach is more readable and easier to support.

$.ajax({
    type: "POST"
    url: url,
    data: data,
    dataType: "json",
    success: function(data) {
        //
    },
    error: function() {
        //
    }
});


4. Event handlers to multiple elements


Often there is a need to add event handlers to page elements (for example, the "delete message" button). And often you can find a similar approach:

$('.comment a.delete').click(function(){
    //
});


There is a problem - add the same handler to a new element (for example, to a dynamically loaded comment). And then I saw a lot of solutions, including redefining all handlers again (often by copy-paste the contents of the handlers):

$('.comment a.delete').unbind('click').click(function() {
    //
});

Solution: in jQuery 1.7 there is an on method that binds event handlers by filtering elements by selector.
example:

$('body').on('click', 'a.external', function(e) {
	//функция будет вызвана при клике на любую ссылку с классом external
});

It is important that this handler also works for dynamically created objects.
It is also worth noting that this approach should be applied wisely. For example, the following code can lead to slower performance and slow down the browser:

$('body').on('mousemove', selector, function() {
	//
});


5. Namespaced events


Despite the fact that namespaced events were added in jQuery 1.2, few people use them (I think most people just don’t know about them).
Рассмотрим example:

$('a').on('click', function() {
	//обработчик 1
});
$('a').on('click', function() {
	//обработчик 2
});

Now suppose we need to remove the second handler from the links. But the bad luck is $ ('a'). Off ('click') will remove both handlers. Namespaced events comes to the rescue. We rewrite the code above:

$('a').on('click.namespace1', function() {
	//обработчик 1
});
$('a').on('click.namespace2', function() {
	//обработчик 2
});

Now it becomes possible to remove the second handler by calling $ ('a'). Off ('click.namespace2');
Read more about namespaced events here: docs.jquery.com/Namespaced_Events

Instead of a conclusion


This is only a small part of the problems that I regularly encounter in someone else's code. I hope this post will help improve the quality of the code.