As we discussed last time, if we have code that’s disorganized and difficult to debug, coding performance and scalability optimizations becomes moot. However, being explicit with your code not only makes your life easier, but actually makes your code faster (say whaaaaaaaat?).
We have to remember that JavaScript isn’t like most other languages. The majority of languages do as they’re told regardless of whether they’re machine languages, scripting languages, markup languages, or whatever else. When you tell Python to make an Array, we get an Array. When you tell ActionScript to create an Object, you get just that – an Object. We’re pretty safe in assuming the language we’re using isn’t lying to us. JavaScript, however, takes another approach. JavaScript has a plan – and you’re a part of it – it’s just going to take your ideas and try to do something better. Problem is.. it’s not always right.
JavaScript, along with the rest of the web platform, is not implemented by one organization. It is an implemented standard and nothing more. So, it is up to several teams to implement this standard and compete with one another (Mozilla, Apple, Microsoft, BlackBerry, Opera, and so on). But, it’s not just enough to implement the standard – it has to be fast, efficient, and… well… better than everyone else’s. Thus, each platform will try to make different assumptions and educated guesses as to what you’re trying to accomplish and find ways to make it run faster. Therefore, the more you cater to a JavaScript Engine’s ability to guess what you’re trying to do, the more you’ll see a boost in performance (and a surprisingly large one too). For example, if you have a sparse array (an array which has a lot of empty indices between ones that have values), an engine will typically manage that array as a dictionary to save resources, but it will cost you when it comes time to iterate over that array.
I could go on for an entire article about which particular optimizations to make (and I definitely will in my next post) but here I’m going to focus on how creating clean explicit code is an amazing start to make your JavaScript run faster.
OK. How do I this?
If you remember from my previous post, I wrote about all sorts of “good practices” junk but, most importantly, I touched on classes and inheritance. We all know JavaScript to be loosely-typed, polymorphic, and prototype-based. These characteristics of JavaScript can be incredibly effective and yet, if used incorrectly, you’re gonna have a bad time.
When we want to extend the functionality of DOM Elements, there’s really only so many ways to do this and the most effective being the following:
HTMLElement.prototype.someFunction = function(param1, param2) { // Your code here };
Depending on the engine, this might compile someFunction into the HTMLElement class or it might create a separate “hidden class” for managing this new functionality behind the scenes. Either way, this slows down our application a great deal and needs to be kept to a minimum and only when necessary. A more common use-case is as follows:
var Point = function Point(x, y) { this.x = x; this.y = y; }; var point3D = new Point(3, 4); point3D.z = 6;
We have some class called Point which did a fine job of being a model for 2-dimensional coordinates. However, at some point in our application, we needed to keep track of an extra coordinate for whatever really good reason we have (don’t ask questions and just believe me) and so we decided to add the property z. To most JavaScript developers, this seems like an awesome solution. The problem is the engine that is interpreting our JavaScript code is going to have troubling guessing what we want to do and, in some cases, will keep a “hidden class” for Point and an arbitrary one for our one-time point3D variable which was created at runtime and, as a result, greatly slowed down our application. Instead we should have created another class called Point3D, or added the property z to the Point class and setting its default value to 0 like this:
var Point = function Point(x, y, z) { this.x = x; this.y = y; this.z = z ? z : 0; };
This way we don’t break previous code that relied on this class and we now have a more generic point model for future 3-dimensional uses.
As our classes become increasingly complex and modifications to existing classes are required, constantly modifying our original class can turn our once easy-to-use reusable code snippet into a monster. This is easily solved with Object Inheritance. For example, perhaps we create a simple class for dispatching generic events like so:
// EventDispatcher (function EventDispatcherStaticScope() { // Give functions an extra somethin' for the EventDispatcher to use. Function.prototype.EventDispatcher_ID = 0; // A static variable for creating unique IDs var ID = 0; // The class itself (note no 'var' makes EventDispatcher global) EventDispatcher = function EventDispatcher() { // Private global variables to this class var _events = {}; // more vars goes here... this.addEventListener = function(event, callback) { // Whatever goes here... }; this.removeEventListener = function(event, callback) { // More codez }; this.dispatchEvent = function(event, data) { // dispatching event logic }; }; })();
Whatever the above class does exactly isn’t important. What is important is what we’re about to do next. Let’s say we want a Timer class for expanding the basal setInterval function JavaScript provides and giving it some event dispatching capabilities. We could do what we first did with Point and just add the necessary properties we need to an instance of EventDispatcher. Unfortunately, that code wouldn’t be reusable and, as we learned, will slow down our app while executing. We could copy and paste all of EventDispatcher‘s functionality but this wouldn’t help us keep our code DRY (Don’t Repeat Yourself) and any fixes would have to be made in two places. We can, however, have Timer be a subclass of EventDispatcher! This way, we can create a class our engine will make good guesses about while, at the same, extending functionality we might only need for now but can be easily reused later. Nice!
Here’s how you would go about it:
var Timer = function Timer(ms) { var __self__ = this; // Internal reference this.inheritFrom = EventDispatcher; this.inheritFrom(); delete this.inheritFrom; // Save us a bit of memory. var _timer = false; // Class's global variable var timerDispatch = function() { __self__.dispatchEvent('timer'); }; this.start = function() { if (!_timer) _timer = setInterval(timerDispatch, ms); }; this.stop = function() { if (!_timer) return; clearInterval(_timer); _timer = false; }; };
And, just so we’re clear, Timer has all the same functions EventDispatcher has – plus its own!
Creating classes and inheriting functionality is a sure way to keep your code running well, the JavaScript engine happy, and your code clean and easy to debug. This sure beats creating generic objects and modifying properties (deleting them and adding new ones) during runtime.
This is a lot to swallow and hence why I tried to focus only a few things for this particular post. Be sure to ask questions and I’ll be sure to answer them!
See you next time!
Image may be NSFW.
Clik here to view.
Clik here to view.
