I feel that JavaScript is a very misunderstood language - especially by many classical Object-Oriented developers (most that I know of anyway, myself included some years ago) that work primarily with C# or Java. This post isn’t to serve as a complete guide, it’s not a best practice guide, and it’s not for beginners - It’s a quick run through the JavaScript’s oddities classical OO developers may find.

Everything is an Object

That’s right, everything in JavaScript is an Object, including functions (apart from primitives, kind of…). Primitive types in JavaScript are much like how they are in C#, they coerce into their Object type counter-part when needed to execute a function. i.e. 'abcefg'.indexOf('ce') and reverts back to primitive type once the function returns.

The “this” keyword

The this keyword behaves differently in JavaScript. In classical OO language such as Java or C#, this refers to the current Object, in JavaScript, this isn’t always necessarily true. this can be changed depending on how it is called.

this in JavaScript, by default, refers to the object this is enclosed in, much like in Java and C#. For example:

1
2
3
4
5
6
7
8
9
10
function Person(name) {
  this.name = name;

  this.sayName = function() {
    console.log(this.name);
  }
}

var cNorris = new Person("Chuck Norris");
cNorris.sayName();

The example snippet shown above would expectedly print “Chuck Norris”.

What if I call the function sayName() - this refers the cNorris object.

But as explained previously, this isn’t always the case. Continuing from the previous example:

1
2
3
4
5
6
7
8
9
10
11
function Person(name) {
  this.name = name;

  this.sayName = function() {
    console.log(this.name);
  }
}

var cNorris = new Person("Chuck Norris");
var bLee = new Person("Bruce Lee");
cNorris.sayName.call(bLee); // prints Bruce Lee

This snippet shown above prints out “Bruce Lee”, but why? Well, as mentioned previously, function’s in JavaScript are also Objects, and we’re actually using the function call to change this.

Why would you want to change what this refers to? For code reuse of course. How? well, let’s take a look at DOM event handling for a second.

HTML

1
2
<input type="text" id="myInput">
<input type="text" id="myOtherInput">

JavaScript

1
2
3
4
5
6
7
8
9
var logValue = function() {
  console.log(this.value);
}; // we're reusing this function

var myInput = document.getElementById('myInput');
var myOtherInput = document.getElementById('myOtherInput');

myInput.addEventListener('change', logValue);
myOtherInput.addEventListener('change', logValue);

Makes a lot of sense doesn’t it? this within logValue function in this case (as how it’s used) refers to the element that fired the event.

Here’s a list of prototype functions that change lexical this for reference:

Scope

JavaScript has no keywords specifically for controlling scope, so how do you control the scope of a function or variable?

var

Using the var keyword, you are making the variable only available to the enclosing function and functions within it. This essentially makes your variable private. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function printOne() {
  var myVar = 1; // private

  function myFunc() {
    function getMyVar() {
        return myVar; // has access to myVar
    }
    console.log(getMyVar());
  }

  myFunc(); // prints 1
}

myFunc(); // error, myFunc does not exist within this scope

Closure

MDN documentation on closure is a must read to fully understand this effect.

One of the things to keep in mind is that, in JavaScript, scope of variables are contained within functions rather than blocks.

Look at this example:

1
2
3
for(var i=0; i < 10; i++) {
    console.log(i);
}

Coming from a C# or Java background, it would be logical to think that this would print out 0 to 9.

What if we change it slighty - what if we add a timeout?

1
2
3
4
5
for(var i=0; i < 10; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

Initially, it might be logical to think that this would print the same result with a 1000ms delay. But it doesn’t, it prints out 10 ten times over (in almost 100% of cases, however it can theoretically be different making this simple piece of code or algorithm if you will, non-deterministic).

We can fix this using a closure:

1
2
3
4
5
6
7
for(var i=0; i < 10; i++) {
    (function(i) {
      setTimeout(function() {
        console.log(i);
      }, 1000);
    })(i);
}

Have a look at the example above carefully - you may be wondering why this worked, and the previous one didn’t. What we are doing is for each loop, we are passing i to an immediately invoked function, also known as an IIFE. When anything gets passed to an IFFE, it becomes part of the IFFE’s state, so in this case, i is passed as a value due to it being a primitive type, creating a new i variable within the scope of the IFFE hiding i in the global scope. Have a look at this example:

1
2
3
4
5
6
7
8
for(var i=0; i < 10; i++) {
    (function(j) {
      setTimeout(function() {
        console.log(j);
        console.log(j === i); // false
      }, 1000);
    })(i);
}

i from the global scope is passed as j within the IFFE, so we are no longer hiding i. If you run this, you will see that j === i will always return false - why? well, i in the global scope has most likely already been incremented to 10, and j in the IFFE’s scope only ever gets to the value of 9.

To summarise, a closure is an assigned self invoking function, this produces an effect whereby, everything within the returned function’s scope is not deallocated from the memory, meaning it gets to maintain its own state.

1
2
3
4
5
6
7
8
9
10
11
12
13
var square = (function() {
    var val = 2;
    return function() {
        var result = val;
        val = Math.pow(val,2);
        console.log(result);
    }
})();


for(var i = 0; i < 4; i++) {
    square();
}

The example above would print out:

1
2
3
4
2
4
16
256

this

You can attach variables to the current this which exposes the function to public through the Object.

1
2
3
4
5
6
function MyObj(val) {
    this.val = val;
}

var myObj = new MyObj(11);
console.log(myObj.val); // 11

prototype

functions attached to the prototype of an Object is exposed to public through the Object.

1
2
3
4
5
6
7
8
9
10
function MyObj(val) {
    this.val = val;
}

MyObj.prototype.printVal = function() {
    console.log(this.val);
}

var myObj = new MyObj(1);
myObj.printVal(); // 1