I put this on my list of JavaScript Warning Words and raised some eyebrows. I have been working to eliminate this from my code both as an exercise to understand closures better and also because this does causes problems. This article shows programming a toggle widget both with and without this

With this

This version could be considered a "standard" approach because the JavaScript community has been lead down this road mostly due to marking. Sun pushed Java with millions of dollars of marketing. Seeing this or self in programming books is the norm. We are just accustomed to this style of programming and it is no wonder JavaScript programmers have pursued this style.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>A Toggle Widget Demo</title> <script type="text/javascript"> // A stub library that could be written cross-browser var LIB = {}; LIB.on = function(element, type, handler, thisObj) { element.addEventListener(type, function(event) { handler.call(thisObj, event); }, false); }; // the widget var ToggleWidget = function(toggler, togglee) { this.toggler = toggler; this.togglee = togglee; LIB.on(toggler, 'click', this.handleClick, this); }; ToggleWidget.prototype.handleClick = function() { var s = this.togglee.style; if (s.display == 'none') { s.display = ''; this.toggler.innerHTML = 'hide'; } else { s.display = 'none'; this.toggler.innerHTML = 'show'; } }; // bootstrap code LIB.on(window, 'load', function() { new ToggleWidget( document.getElementById('toggler'), document.getElementById('togglee')); }); </script> </head> <body> <p> <span id="toggler" style="text-decoration:underline;">show</span> <span id="togglee" style="display:none;">SURPRISE!</span> </p> </body> </html>

Without this

This second version doesn't use this . Instead closures are used more directly.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>A Toggle Widget Demo</title> <script type="text/javascript"> // A stub library that could be written cross-browser var LIB = {}; LIB.on = function(element, type, handler) { element.addEventListener(type, handler, false); }; // the widget var makeToggleWidget = function(toggler, togglee) { LIB.on(toggler, 'click', function() { doToggle(toggler, togglee); }); }; var doToggle = function(toggler, togglee) { var s = togglee.style; if (s.display == 'none') { s.display = ''; toggler.innerHTML = 'hide'; } else { s.display = 'none'; toggler.innerHTML = 'show'; } }; // bootstrap code LIB.on(window, 'load', function() { makeToggleWidget( document.getElementById('toggler'), document.getElementById('togglee')); }); </script> </head> <body> <p> <span id="toggler" style="text-decoration:underline;">show</span> <span id="togglee" style="display:none;">SURPRISE!</span> </p> </body> </html>

Comparison

Programmers often site that using this and prototype are more efficient in memory space. Compare the two examples above. The second version's code is a marginally shorter but in longer programs the second style seems to be noticeably shorter. The difference is where the extra closures are made. In the first example there is an extra closure created in every call to LIB.on to set the this object when handleClick is called. In the second example, the extra closure is created in the makeToggleWidget function. At runtime the first example has more work to do as it uses Function.prototype.call to handle the user's click.

In the first version the application programmer concentrates on object-oriented programming and leaves the necessary closures to the library. In the second example the application programmer concentrates on the closures directly. As JavaScript programming has evolved, the direct use of closures has become more common practice. Programming with this often involves thinking both in the object-oriented style and closure style. Programming like the second version means just thinking in the closure style.

The second example has some more advantages...

The doToggle is available for use at any time. Just send it two DOM elements and it will work. If you didn't want the doToggle function out in the open you could hide it in a module pattern or namespace it somehow. Calling the handleClick generically with two DOM elements would be quite ugly.