Invocation Patterns in JavaScript

There are four different invocation patterns in JavaScript that determine what the hidden parameter this is bound to.1

Method Invocation Pattern

A method is a function tied to a property on an object. For methods, this is bound to the object upon invocation. For example:

var person = {
    name: 'Calvin',
    age: 25,
    greet: function () {
        alert('My name is ' + this.name + '.');
    }
};
person.greet(); //My name is Calvin.

In this example, this is bound to the person object upon invoking greet because greet is a method of person.

Function Invocation Pattern

For functions that are not properties on objects, this is bound to the global object. This is not very intuitive and is often considered one of the ‘bad parts’ of JavaScript–a mistake in language design. Naturally, you’d think this would be bound to the parent function, and that would have been much more helpful. Regardless, most developers overcome this problem by assigning this to a variable in the parent function. For example:

// Add a new method to person
person.calculateAge = function (yearsFromNow) {
    var self = this;

    function yearsOld() {
        return self.age + yearsFromNow;
    }

    alert('I will be ' + yearsOld() + ' years old ' + yearsFromNow + ' years from now.');
}
person.calculateAge(10); //I will be 35 years old 10 years from now.

In this example, I maintain a reference to the context of this by assigning it to the variable self. At the time of assignment, this is bound to the person object. As a result, I can access the property age on the person object from within the yearsOld function. self and that are common names for variables that maintain the context of this.

What if I had used this instead of self?

person.calculateAgeWrong = function (yearsFromNow) {
    function yearsOld() {
        return this.age + yearsFromNow; //NaN
    }

    alert('I will be ' + yearsOld() + ' years old ' + yearsFromNow + ' years from now.');
}
person.calculateAgeWrong(10);

Constructor Invocation Pattern

In JavaScript, functions can be invoked with the new prefix similar to the way objects are constructed in other languages. When this happens, this is bound to the new object. In addition, the resulting object is created with a link to the hidden prototype property of the function. This is what makes JavaScript a prototypal inheritance language as opposed to a classical inheritance language. There are no classes, but objects can inherit properties from other objects.

Functions that are designed to be called with the new prefix are by definition constructors. These functions are distinguished from others by using PascalCase as opposed to camelCase.

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

Person.prototype.greet = function () {
    return this.name + ' says hi.';
};

alert(new Person('Calvin').greet()); //Calvin says hi.

Notice the greet function uses this to access the name property. this is bound to Person.

Apply Invocation Pattern

As a functional object-oriented language, JavaScript makes it possible for functions to have methods as well. The apply function is a method on the Function.prototype–the prototype for all JS functions. apply makes it possible to use one object’s method in the context of another. We can do so by supplying an array with the correct number arguments and and the object to which this will be bound, also known as the context. Therefore, apply can take two arguments: (1) a context for this and (2) an array of arguments that will be applied to the method at hand.

var calvin = new Person('Calvin');
var hobbes = {name: 'Hobbes'};
alert(calvin.greet.apply(hobbes)); //Hobbes says hi.

Even though hobbes does not have a greet method, we can still apply the greet method from calvin because hobbes has a name property. If hobbes didn’t have a name property, the invocation would fail. This example demonstrates the invocation of the apply function with only one argument. greet doesn’t have any parameters so we didn’t provide apply an array of arguments.

Let’s say we have a method greetFriends that takes two arguments–two objects with a name property.

Person.prototype.greetFriends = function (friendA, friendB) {
    return this.name + ' says hi to ' + friendA.name + ' and ' + friendB.name + '.';
};

var bill = {name: 'Bill Watterson'};

alert(calvin.greetFriends.apply(bill, [calvin, hobbes]));
//Bill says hi to Calvin and Hobbes.

In this example, we supply two arguments to the apply function: bill as the context for this and an array with our two person objects. calvin and hobbes become the parameters friendA and friendB in greetFriends.

What if we were to have a method with an unpredictable number of arguments?

Sometimes in a web app you want to make an asynchronous request to a web server, often to a web API to fetch or modify some data. Sometimes you have to make multiple web requests and you don’t know how many because it depends on dynamic user input. Furthermore, you may want to execute some additional code after all the web requests are complete, so you might use a library like jQuery or Q that has a deferral/promise implementation. If you were using jQuery, your code might look something like the following, but with real data and a real purpose, not just to print out numbers:

// example & real world = set variables
var num = Math.ceil(Math.random() * 10),
    delay = 0,
    deferreds = [],
    element = document.getElementById('counter');

// example = print number when deferred is resolved
// real world = make asynchronous GET, POST, PUT, PATCH or DELETE request
function defer() {
    delay += 1000;
    return $.Deferred(function (def) {
        setTimeout(function () {
            element.innerHTML = --num;
            def.resolve();
        }, delay);
    }).promise();
}

// example = execute a random number of deferreds
// real world = execute a number of aync requests based on user input
// both = hold promises in an array
for (var i = num; i > 0; i--) {
    deferreds.push(defer());
}

// example = start off the countdown
element.innerHTML = num;

// example & real world = apply promises--unknown number until runtime
$.when.apply($, deferreds)
    .always(function () {
        // example & real world = take action after all promises are resolved
        element.innerHTML = num + '...done.';
    });

Since this example uses jQuery, I created a JSFiddle you can run to see the result.

References

  1. The four invocation patterns discussed were taken from JavaScript: The Good Parts by Douglas Crockford. I highly recommend reading this short book if you want to get serious about JavaScript.

More JavaScript

 

Closure in JavaScript

Closure is one of those terms you hear thrown around a lot in JavaScript development, but it’s often misunderstood and mistaken for scope. Scope is related and plays an important role in closure, but is not the same thing.

Closure is when a function has access to its original context. Here’s the Mozilla Developer Network’s take on closure:

A closure is a special kind of object that combines two things: a function and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.

An example:

function speak() {
    var greeting = 'hi';
    function saySomething() {
        console.log(greeting);
    }
    saySomething();
}
speak(); //hi

In this example, saySomething is a closure–it is a function that has access to its original context. Put differently, it is a function AND the environment in which it was created because it can access greeting, a variable from the parent function’s scope. greeting is not part of saySomething‘s scope.

Another example:

function speak(name) {
    var greeting = 'hi';
    function saySomething() {
        console.log(name + ' says ' + greeting);
    }
    saySomething();
}
speak('billy'); //billy says hi

In this example, speak defines a variable AND takes an argument. saySomething is still a closure–it can reference variables and parameters that are part of its environment.

A common misconception about closure is that you have to return a function for a closure to exist. This is NOT true. However, let’s expand the existing example by returning the saySomething function instead of executing it:

function speak(name) {
    var greeting = 'hi';
    function saySomething() {
        console.log(name + ' says ' + greeting);
    }
    return saySomething;
}
var billySpeaks = speak('billy');
var nobodySpeaks = speak('nobody');
billySpeaks();   //billy says hi
nobodySpeaks();  //nobody says hi

You’d think name and greeting would only be accessible at the time of execution, but that’s obviously not the case. That’s because local variables and arguments that are in scope at the time a closure is created remain accessible–they are part of the environment.

In the preceding example, speak is a closure that consists of the parameter name, the local variable greeting and the function saySomething when it was created. Therefore, billySpeaks and nobodySpeaks have access to them after execution has finished.

References

More JavaScript

Hoisting in JavaScript

In order to test my understanding of hoisting, closure and scope in JavaScript, I put together a number of exercises (with the help of my colleague Kevin). Each successive exercise builds on the last and the output of the function can be viewed by hovering or clicking the text in the output section below the respective exercise.

What is the output?

(function () {
    var test = 5;

    if (false) {
        test = 7;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output?

(function () {
    var test = 5;

    if (false) {
        var test = 7;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Is test global?

(function () {
    test = 5;

    if (false) {
        var test;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Is test global?

(function () {
    test = 5;

    if (false) {
        //var test;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Will it error and break? Is test defined?

(function () {
    if (false) {
        var test = 3;
    } else {
        console.log(test + 2);
    }
}());
hover for result

NaN

What is the output? Is one defined? Will it error? Or is it one of these digits: 3, 4, 5, or 6?

(function () {
    test = 5;

    if (false) {
        var test = 3;
    } else {
        console.log(one(test));
    }

    function one(value) {
        return value + 1;
    }
}());
hover for result

6

What is the output? Is one defined?

(function () {
    test = 5;

    if (false) {
        var test = 3;
    } else {
        console.log(one(test));
    }

    var one = function (value) {
        return value + 1;
    };
}());
hover for result

TypeError: undefined is not a function

Is the function one hoisted to the top of the highest scope? Is one a function or an integer? What is one where? ;)

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        }(test));

    console.log(one);
}());
hover for result

1

Is one hoisted to the top of the highest scope?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));
}());
hover for result

TypeError: undefined is not a function

What are the values of one? What is the output? Does recursion still apply? Which one declarations have precedence where?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    function one(value) {
        return value;
    }
}());
hover for result

3,1

Is one still hoisted to the top even though it’s immediately executed? Does it behave the same as before?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    function one(value) {
        return value;
    }(4);
}());
hover for result

3,1

Is one hoisted to the top now that it’s enclosed by parenthesis?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    (function one(value) {
        return value;
    }(4));
}());
hover for result

TypeError: undefined is not a function

Is one hoisted to the top even though it’s immediately executed and assigned with a name?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
}());
hover for result

TypeError: undefined is not a function

What’s the output?

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
    console.log(identity);
}());
hover for result

1,4

What’s the output?

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
    console.log(identity(3));
}());
hover for result

TypeError: number is not a function

Lessons Learned

  • When var is not used, variables are made global
  • Variable names take precedence over function names (in the case of duplicates)
  • Variable declarations (e.g. var myObj) are hoisted to the top of function scope; however, assignment is NOT hoisted
  • Function declarations (e.g. function myFunc() { }) are hoisted to the top of function scope
  • Function expressions (e.g. var myFunc = function someFunc() { }) are NOT hoisted to the top of function scope
    • They are treated like variable declarations–the variable definition is hoisted, but the assignment is not hoisted
    • someFunc cannot be called outside of its assignment; someFunc is undefined (ReferenceError); must use myFunc
  • Immediately executing function declarations has no effect on hoisting–the function will still be hoisted to the top of function scope

More JavaScript

Coercion in JavaScript

Bang and Double Bang

To me, coercion in JavaScript is another topic I’ve found interesting to explore. unexpected results. When using the bang (!)–also known as logical not–or double bang (!!) before a value, JavaScript coerces the value to a boolean and yields the opposite value:

!false                      //true
!0;                         //true
!!0;                        //false
typeof !!0                  //boolean
typeof !!0 == "boolean"     //true

Now to take it a step further by comparing the coerced values with the double equals operator:

!!0 == false    //true
!!'' == ''      //true
!!0 == 0        //true
!!1 == 1        //true
!!'0' == '0'    //false

How about that last line?

JavaScript coerces the first operand and then evaluates the entire expression. The first operand coerces to true leaving true == '0' as the expression to be evaluated. Under this scenario, the types of each value are different and one of them is a boolean, so JavaScript tries to convert each to a number. This results in 1 === NaN, which is obviously false. For another look at how the double equals comparison operator works in JavaScript, read this blog post.

If Blocks

In the context of if blocks, coercion applies very similarly.

if ('hi') { 
	console.log('hi');  //hi
}
if (1) { 
	console.log(1);     //1
}
if ('') { 
	console.log('');    // statement never reached
}

JavaScript coerces the string 'hi' the same way it would if we put !!'hi'. We could pass in a variable and it would be coerced the same way as well.

var val = 'hi';
if (val) { 
	console.log(val);	//hi
}

Therefore…

if ('hi') { 
	console.log('hi' == false);	//false
	console.log('hi' == true);	//false
}

Wait a second. Shouldn’t console.log('hi' == true); produce true? This is mostly a mind trick. We see 'hi' is truthy in the if statement, but when it’s compared to true with the double equals operator, it behaves similar to the example above–JS tries to convert 'hi' to a number first which results in NaN and then the whole expression is evaluated and it produces false. If this doesn’t make sense, you really need to read up on the double equals operator to understand how it works.

Why !!

So why would you ever use !!? It’s mostly a concise way of converting a value to a boolean or making sure it is a boolean. Alternatively, you could use the Boolean function, but it’s important to understand this has some tricks too. Before revealing the result below or reading any further, take a guess at what each line yields:

!!Boolean(false)
!!new Boolean(false)
hover for result

false,true

The new prefix constructs a boolean object. An object coerced yields true.

!new Boolean(false) !== !!!{}
hover for result

false

More JavaScript

Logical Operators in JavaScript

Logical operators in JavaScript can be a clean and simple way to return or set values without introducing extra if statements.

console.log(true || false);                //true
console.log(true && false);                //false
console.log(true && 0 && false);           //0
console.log(true && 'string' && 1);        //1
console.log(false || 'string' || false);   //string
console.log(false || 0 || 'string');       //string
console.log(false || 1 && 'string');       //string
console.log(false || 1 && 0 && 'string');  //0
console.log(false || 1 && 0 || 'string');  //string

This comes in hand when you want to make sure a variable has a value. This can be a concise way of preventing errors.

var persons = [
    {id: 1, name: 'joe', age: 22},
    {id: 2, name: 'harry', age: 59},
    {id: 3, name: 'will', age: 30}
];
var index = 19;
var person = persons[index];
console.log(person.name); //error

Well that’s no good. Let’s say index is derived from user input and you don’t want it to error if the index is out of bounds:

console.log(person && person.name); //undefined

Much better. You could also test index. If it’s not a valid value, then set it to a default.

index = index < persons.length || 0; //0
var person = persons[index];
console.log(person && person.name); //joe

This is a very contrived example, but hopefully you get the idea.

Arguably, adding logical operators on the same line doesn’t always make for the most readable code, but with practice I’ve found it to be quite readable and concise, as long as you don’t pack too many operations on one line.

That said, it’s not always easily tested. Each line of code performs multiple functions, so you can’t put break points right where you want them.

More JavaScript

Double Equals Comparison Operator in JavaScript

I’ve been doing a lot of development in JavaScript lately. I’ve found that evaluating values using the double equals comparison operator in JavaScript can produce some intriguing results.

First, I want to clarify the difference between double equals (==) and triple equals (===) in JavaScript. Double equals evaluates equality WITH type coercion while triple equals evaluates equality WITHOUT type coercion. Thus:

0 == false     //true
0 === false    //false

Double Equals (==)

Now for some more examples. For starters, when comparing '0' and '' to false, both evaluate to true:

'0' == false    //true
'' == false     //true

However, when we compare them against each other:

'0' == ''   //false

Interesting. Why is that? This is how the double equals works:

Equal (==)

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory (Comparison Operators, Mozilla Developer Network).

So, with the example at hand, JS evaluates the operand type first. Since neither operand is a number or boolean and at least one of the operands is a string, they are evaluated as strings. (In this case, just so happens both operands are strings.) Next JS evaluates the values, which are different. Despite the “falsey” nature of both zero and the empty string, as string types they are altogether different values and therefore not equal.

Let’s take a look at a couple other intriguing examples.

'' == '0'           // false
0 == ''             // true
0 == '0'            // true
false == 'false'    // false
false == '0'        // true
false == undefined  // false
false == null       // false
null == undefined   // true
' \t\r\n ' == 0     // true

To explain some of these examples that were perplexing to me the first time I examined them…

When comparing false == 'false', JS tries to convert both to numbers. The result is 0 === NaN, which is of course false. This also explains why false == '0' is true–because it boils down to 0 === 0.

It appears that when ' \t\r\n ' is converted to a number, JS converts it to 0. At any rate isNaN(' \t\r\n ') results in false, which tells me that when converted to a number, ' \t\r\n ' does NOT result in NaN. Therefore ' \t\r\n ' must boil down to 0 since ' \t\r\n ' == 0 is true.

For further reading and in depth analysis with helpful tables, I highly suggest reading Truth, Equality and JavaScript by Angus Croll.

Final Thoughts

Some developers avoid using == in their code because they don’t understand it and it’s confusing. I think it’s important to understand how == works since this will lead to language mastery. Furthermore, if you don’t use ==, your colleagues or 3rd party libraries will, and if you don’t understand it, then you are disempowered. After you understand ==, I see no problem with not using it. But simply avoiding it because it’s confusing and you don’t understand it seems unwise.

If you’re interested in the actual specification: Abstract Equality Comparison Algorithm

If performance is of concern when using == vs ===, these may be worth perusing:

More JavaScript

Block Scope and Function Scope in JavaScript

Block Scope

JavaScript does NOT have block scope (think if blocks and the like). Variables used before assignment will be undefined and variables used after assignment will yield the expected value.

function a() {
    var hi = 'hi';
    console.log(hi);  //hi
    console.log(bye); //undefined

    if (true) {
        var bye = 'bye';
        console.log(hi);  //hi
        console.log(bye); //bye
    }
    console.log(hi);  //hi
    console.log(bye); //bye
}

Why? Because JavaScript hoists all variable declarations to the top of the function upon rendering the code. So effectively it is interpreted like this:

function a() {
    var hi, bye;    
    hi = 'hi';
    console.log(hi);  //hi
    console.log(bye); //undefined

    if (true) {
        bye = 'bye';
        console.log(hi);  //hi
        console.log(bye); //bye
    }
    console.log(hi);  //hi
    console.log(bye); //bye
}

The variable declarations hi and bye are hoisted to the top of the function and assigned as you would expect. As a result, bye is undefined when it is first referenced outside the if block and we don’t get an error. However, the second time it is referenced outside the if block, it has the appropriately assigned value, even though it is out of block scope.

Function Scope

JavaScript DOES have function scope. Variables defined in inner function scope and used in outer function scope will result in an error because the variable has not been defined in scope.

function a() {
    var hi = 'hi';
    console.log(hi);  //hi
    console.log(bye); //error

    function b() {
        var bye = 'bye';
        console.log(hi);
        console.log(bye);
    }
    b();
    console.log(hi);
    console.log(bye);
}

Variables used in outer function scope even after inner function scope assignment will result in error as well; however, if a variable has been defined in outer function scope, JavaScript will reach those variables and refer to their values within inner function scope.

function a() {
    var hi = 'hi';
    function b() {
        var bye = 'bye';
        console.log(hi);  //hi
        console.log(bye); //bye
    }
    b();
    console.log(hi);  //hi
    console.log(bye); //error
}

What about functions defined in inner scope and referenced in outer scope?

function a() {
    var hi = 'hi';
    function b() {
        var bye = 'bye';
        console.log(hi);  //hi
        console.log(bye); //bye
    }
    b();
}
b(); //error

The same holds true for them as well. Function scope is strict.

More JavaScript