Five Common JavaScript Misunderstandings

2011-10-31 00:00:00 +0000 by Alex R. Young

Over the last few years more people have been drawn to JavaScript thanks
to libraries like jQuery and innovative server-side projects like Node.
However, JavaScript is deceptively easy to learn for existing
developers, and there are a few frustratingly awkward pitfalls for
newcomers. I've quietly been keeping notes on some of these pitfalls,
and have selected a few of my favourites in this post.

Too Many Callbacks!

New Node developers like to complain about callbacks. Deeply nested
callbacks don't read particularly well, but this isn't necessarily
JavaScript's fault. One way to mitigate this is through flow control
techniques, and chainable APIs are probably the most popular technique
in this area. For example, consider jQuery where the API feels very


If you're knee-deep in callbacks, check to see if the library you're
using has an alternative chainable API. A lot of popular libraries do,
like Underscore.js.

Chainable APIs work by returning this from their methods.
It can be quite hard to make some APIs work this way, but masking the
underlying complexity is often worth it.

There are plenty of flow control libraries available through
npm that solve this (and similar) style problems.


Experienced classical object-oriented developers often get frustrated
with JavaScript's prototypes and recreate traditional class and
inheritance patterns. I think the lack of OO-related keywords is the
main reason for this. However, there's no need to shy away from
prototypes, and prototypal inheritance is surprisingly easy to learn:

var user;

function Person(name) {
  this.name = name;

Person.prototype.greet = function() {
  console.log('Hello', this.name);

// Admin inherits from Person

function Admin(name) {
  this.name = name;

Admin.prototype = new Person;

user = new Admin('alex');

// This method was defined on Person

The key line is Admin.prototype = new Person;. I only
really understood this when I started to think about prototype chains:
Inheritance and the prototype chain.

Scope and Callbacks in Loops

I've fallen foul of this a few times over the years. When looping over a
set of values, people often mistakenly think an anonymous function will
capture the current state of the variables in the loop:

var assert = require('assert')
  , names = ['alex', 'molly', 'yuka']
  , name
  , i;

for (i = 0; i < names.length; i++) {
  name = names[i];

  if (name === 'alex') {
    setTimeout(function() {
      assert.equal(name, 'alex');
    }, 10);

The callback will execute in the future, at which point the name will
have changed because it hasn't been bound the way it seems like it
should. This will work as expected:

var assert = require('assert')
  , names = ['alex', 'molly', 'yuka'];

names.forEach(function(name) {
  if (name === 'alex') {
    setTimeout(function() {
      assert.equal(name, 'alex');
    }, 10);

People often use for instead of an iterator when
performance is desired, but in certain cases callback-based iteration
might be more readable.

this in Nested Functions

What's the value of this in a nested function?

var user;

function Person(name) {
  this.name = name;

Person.prototype.nested = function() {

  (function() {

user = new Person('alex');

The first console.log will show { name: 'alex'
, but the second will show the global object (window in client-side code). This is why a lot of code sets var self = this at the start of a method.

Future Reserved Words

The ECMA standards define Future Reserved Words that include commonly
used words like class, extends, and
super. It's probably a good idea to avoid using these
words; check with the specifications if you're unsure of a particular