JavaScript: why you shouldn't use HTML event attributes anymore

Very often, web-developers uses HTML events attribute to call a JavaScript function on a specific event (eg: onclick="foo()"). Let's see together why this is a terrible idea and how you can listen events without those abominations.

The global scope

Don't pollute!

A very common bad practice is to pollute the global scope. To summarize, global scope pollution appends every time you declare an identifier outside of a function (eg: global variables, global functions). What can happen because of such identifiers declared in the global scope ? Simple: a naming collision. Example :

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <p id="bar">plop</p>
    <p id="baz">plop</p>

    <script type="text/javascript">
    var foo = 'Sed ut perspiciatis unde omnis iste natus error.';
    document.getElementById('bar').innerHTML = foo;

    function foo() {
        return 'Lorem ipsum dolor sit amet.';
    }
    document.getElementById('baz').innerHTML = foo();
    </script>
  </body>
</html>

Such collisions could easily append because:

  • you're working with other people ;
  • you're using third-party scripts ;
  • inattention ;
  • numerous others reasons.

Eco-friendly coding

There's two good practices you should always use in order to stop global scope pollution :

  • Write your code in anonymous self-calling functions ;
  • Use the keyword var for variable declaration, otherwise it will be declared in the global scope.
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <p id="bar">plop</p>
    <p id="baz">plop</p>

    <script type="text/javascript">
(function() {
    var foo = 'Sed ut perspiciatis unde omnis iste natus error.';
    document.getElementById('bar').innerHTML = foo;
})();

(function() {
    function foo() {
        return 'Lorem ipsum dolor sit amet.';
    }
    document.getElementById('baz').innerHTML = foo();
})();
    </script>
  </body>
</html>

What about HTML events attribute?

Using the HTML attribute has one big downside: you can only call something defined in the global scope. Because the function is stuck inside an anonymous function, we cannot call it. Therefore, using the HTML events attribute requires global scope pollution and is error-prone.

Event listening without HTML

Pure JavaScript

Because we cannot use the HTML attributes anymore, we'll use JavaScript only. Let's have a look at the addEventListener method. This method is available on many elements, including DOM elements. The first two parameters are the most interesting: a string containing the event name and a callback function which will be called each time the event is triggered.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <p id="bar">Click me!</p>

    <script type="text/javascript">
(function() {
    document.getElementById('bar').addEventListener('click', function() {
        this.innerHTML = 'Lorem ipsum dolor sit amet.';
    });
})();
    </script>
  </body>
</html>

Using jQuery

jQuery defines many events on its objects:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
  </head>
  <body>
    <p id="bar">Click me!</p>

    <script type="text/javascript">
$(document).ready(function() {
    $('#bar').click(function() {
        $(this).html('Lorem ipsum dolor sit amet.');
    });
});
    </script>
  </body>
</html>

See also