Skip to main content

A (Re)-Introduction to JavaScript

Popularity Report

Total Popularity Score: 0

Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Rank

Related Lists

Bookmark History

Public Comment

on 2006-08-02 by garyburge

Notes made in preparation for a three hour tutorial.

on 2006-08-05 by lukehardiman

notes for willison's reintroduction talk / presentation

on 2006-09-02 by bluecockatoo

Good information on how to avoid IE memory leaks if using Javascript closures.

Public Sticky notes

Why a re-introduction? Because JavaScript has a reasonable claim to being the world's most misunderstood programming language. While often derided as a toy, beneath its deceptive simplicity lie some powerful language features. The last year has seen the launch of a number of high profile JavaScript applications, showing that deeper knowledge of this technology is an important skill for any web developer.

Highlighted by cvdlinden

An unfortunate side effect of closures is that they make it trivially easy to leak memory in Internet Explorer. JavaScript is a garbage collected language - objects are allocated memory upon their creation and that memory is reclaimed by the browser when no references to an object remain. Objects provided by the host environment are handled by that environment.

Browser hosts need to manage a large number of objects representing the HTML page being presented - the objects of the DOM. It is up to the browser to manage the allocation and recovery of these.

Internet Explorer uses its own garbage collection scheme for this, separate from the mechanism used by JavaScript. It is the interaction between the two that can cause memory leaks.

A memory leak in IE occurs any time a circular reference is formed between a JavaScript object and a native object. Consider the following:

function leakMemory() {
    var el = document.getElementById('el');
    var o = { 'el': el };
    el.o = o;
}

The circular reference formed above creates a memory leak; IE will not free the memory used by el and o until the browser is completely restarted.

The above case is likely to go unnoticed; memory leaks only become a real concern in long running applications or applications that leak large amounts of memory due to large data structures or leak patterns within loops.

Leaks are rarely this obvious - often the leaked data structure can have many layers of references, obscuring the circular reference.

Closures make it easy to create a memory leak without meaning to. Consider this:

function addHandler() {
    var el = document.getElementById('el');
    el.onclick = function() {
        this.style.backgroundColor = 'red';
    }
}

The above code sets up the element to turn red when it is clicked. It also creates a memory leak. Why? Because the reference to el is inadvertently caught in the closure created for the anonymous inner function. This creates a circular reference between a JavaScript object (the function) and a native object (el).

There are a number of workarounds for this problem. The simplest is this:

function addHandler() {
    var el = document.getElementById('el');
    el.onclick = function() {
        this.style.backgroundColor = 'red';
    }
    el = null;
}

This works by breaking the circular reference.

Surprisingly, one trick for breaking circular references introduced by a closure is to add another closure:

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    }
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

The inner function is executed straight away, and hides its contents from the closure created with clickHandler.

Another good trick for avoiding closures is breaking circular references during the window.onunload event. Many event libraries will do this for you.

Highlighted by bluecockatoo

Highlighted by knightnet

on 2008-07-17 by knightnet

The comments on && and || using short-circuits and the resultant examples are particularly nice.

The && and || operators use short-circuit logic, which means they will execute their second operand dependant on the first. This is useful for checking for null objects before accessing their attributes:

var name = o && o.getName();

Or for setting default values:

var name = otherName || "default";

Highlighted by knightnet