JavaScript series: Lexical scope, closures, function scope and block scope

Lexical scope

Lexical scope which is also sometimes called static scope defines how variable names are resolved in nested functions.

function myOuterFunction() {
    var outerVariable = 10;

    console.log(globalVariable); // 5

    function myInnerFunction() {
        console.log(globalVariable); // 5
        console.log(outerVariable); // 10
    }

    myInnerFunction();
}

var globalVariable = 5;

myOuterFunction();

With lexical scope we can access variables defined in parent scopes. Above outerVariable is declared in the scope of myOuterFunction but is still accessible inside the scope of myInnerFunction. The globalVariable is declared in the global scope and will be accessible everywhere.

function myFunction() {
    var myVariable = 10;

    console.log(myVariable); // 10
}

var myVariable = 5;

myFunction();

console.log(myVariable) // 5

Variables declared in an outside scope can be overriden in a child scope. We’ve declared myVariable in the global scope and then declared it again in the scope of myFunction. We can see that myVariable has different values depending on which scope you’re in.

function myFunction() {
    var myVariable = 10;

    console.log(myVariable); // 10
}

myFunction();

console.log(myVariable) // ReferenceError

Variables declared in an inner scope is not accessible by an outer scope.

Closure

Closure is when a function remember its lexical scope even when it’s referenced and executed elsewhere and even after the outer function has returned.

function functionBuilder() {
    var count = 0;
    return function () {
        count++;
        console.log("Number of times this function has been called: " + count);
    }
}

var myFunction = functionBuilder();

myFunction(); // 1
myFunction(); // 2
myFunction(); // 3

With the help of closures we can have private variables. Here we’ve created a function named functionBuilder which declares a variable named count and then returns a function which just increment count by one and logs to the console how many times it’s been called. The count variable is now inaccessible in the global scope. But our returned function still has access to it. This is what closure is all about.

var myModule = (function () {
    var count = 5;

    function printValue() {
        console.log("Value: " + count);
    }
    
    return {
        increment: function () {
            count++;
            printValue();
        },
        decrement: function () {
            count--;
            printValue();
        }
    };
} ());

myModule.increment(); // 6
myModule.decrement(); // 5
myModule.increment(); // 6

myModule.printValue(); // Won't work
myModule.count; // Won't work

To use a modular design pattern we can make use of Immediately-invoked function expression(IIFE) which is a function that is executed immediately. Here we returned an object with public methods on it. The public methods then have access to our private state.

Function scope

Before a function starts executing an executiion context is created and pushed to the stack. The execution context contains information about its lexical environment and which functions and variables that belongs to the scope. That means that every variable and function declaration is known before the function starts executing. Before ECMAScript 6 JavaScript only has function scope and not block scope like any C based language.

function functionScope() {
    if(true) {
        var a = 1;
    }
    
    console.log(a);
}

functionScope();

This is valid code in JavaScript and it is called hoisting, meaning that every variable declared with the var statement will be lifted to the top of the function and available everywhere in the function even if it’s declared inside a block.

console.log(a); // undefined
var a = 1;
console.log(a); // 1

console.log(b); // ReferenceError

It’s important to understand the difference between declaring and initializing a variable. Above we can see that a is accessible before the line declaring it but it’s not initialized which means it’s value is undefined. The last line shows us that forgetting to declare a variable gives us a ReferenceError. Because of hoisting it’s good practice to declare variables at the top of a function so that it’s clear that they are function scoped.

var functions = [];
for (var i=0;i<3;i++) {
    functions[i] = function() {
        console.log(i);
    }
}

functions[0](); // 3
functions[1](); // 3
functions[2](); // 3

Coming from a block scoped language can sometimes trick you to believe that the above code would print 1 2 3, but that is not correct because of function scope and closures. Closure is when a function remembers its lexical scope even after it’s referenced elsewhere and because of the variable called i is function scoped it’s value for each function in the array will be 3.

var functions = [];
for (var i = 0; i < 3; i++) {
    functions[i] = (function (index) {
        return function () {
            console.log(index);
        }
    }(i));
}

functions[0](); // 0
functions[1](); // 1
functions[2](); // 2

But we can solve this by creating a wrapping function which gives us a new function scope. Here we created an IIFE which takes i as a parameter and then returns our function. The reason that it works is beacuse it’s creating a new scope for our returned function in each iteration.

Block scope

As of ECMAScript 6 you have the possibility to have block scope in JavaScript with the new let and const keyword. Because of how JavaScript declares variables let and const is also hoisted internally. But you will get a ReferenceError using it before the declare statement.

function test() {
    if (1 === 1) {
        let a = 1;
    }

    console.log(a); // ReferenceError
}

test();

As we see above the variable called a declared with let is local to the if statement.

function test() {

    let a = 2;
    //let a = 3; // Throws an error. Already declared

    console.log(a); // 2
}

let a = 1;
test();
console.log(a); // 1

The lexical aspect works the same as with var but you can’t redeclare a variable in the same block scope with let.

var functions = [];
for (let i=0;i<3;i++) {
    functions[i] = function() {
        console.log(i);
    }
}

functions[0](); // 0
functions[1](); // 1
functions[2](); // 2

With the let keyword we don’t have to create a wrapping function to have a unique value of variable i in each iteration. This is because every iteration itself is a new block scope.

Conclusion(tl;dr)

Lexical scope defines how variable names are resolved in nested functions.

Closure is the mechanism of a function remembering it’s lexical scope even when the functions is referenced elsewhere and even after the parent function has returned.

Before ECMAScript 6 JavaScript only has function scope meaning that every variable created with the var keyword is accessible in the entire function. It’s declared even before the row of the declaration but it’s value isn’t initialized. This is called hoisting.

In ECMAScript 6 we’ve got the let and const keywords that lets us declare variables block scoped.

JavaScript series: The ThisBinding

The this keyword in Javascript can be confusing even for experienced developers. What this is a reference to depends on how the function was called. It’s a runtime binding that has nothing to do with where the function was declared. The ThisBinding makes it possible to use a function in multiple contexts rather than creating multiple versions of it.

To find out what the this keyword will be a reference to you need to find the call-site of the function. In other words where the function was called either by looking at your code or through a debugger. Then you’ll have to inspect the call-site to determine which of the four rules explained below that applies.

The new binding

The first rule with the highest precedence is the new binding.

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

var personObj = new Person("Jonathan");
console.log(personObj.name); // Jonathan

When the new operator is put in front of a function call it creates a new object and assigns it’s reference to the this keyword.  The newly created object also gets it’s prototype to reference Person.prototype which in this case is an empty object. To learn more about the prototype read the post Prototype-based inheritance of my Javascript series.

If the function does not explicitly return an object the object this is referencing will be returned. Should the function return anything else that is not an object that return value will be ignored and the object referenced by this will be returned.

Explicit binding

The explicit binding forces this to reference a specified object.

function sayHi() {
	console.log("Hi " + this.name );
}

var person1 = {
	name: "Jonathan"
};

var person2 = {
	name: "Kalle"
};

sayHi.call(person1); // Hi Jonathan
sayHi.apply(person2); // Hi Kalle

With .call and .apply we can set this to reference the object we want on any function call(except functions that is using hard binding).

Function.prototype.apply(thisArg, [argsArray])
Function.prototype.call(thisArg[, arg1[, arg2[, …]]])

The call and apply function is inherited from Function.prototype. They achieve the same goal but with different signatures. The apply function takes an array as it’s second parameter which will be the arguments for the function invoked. The call function requires the arguments to be listed explicitly as parameters.

Hard binding

Sometimes we don’t want the caller to change the thisBinding. We can then use hard binding.

function sayHello() {
	console.log(this.name);
}

var person1 = {
	name: "Jonathan"
};

var person2 = {
	name: "Kalle"
};

var origSayHello = sayHello;
sayHello = function() {
	origSayHello.call(person2);
};

sayHello.call(person1); // Kalle

By saving a reference to sayHello and then creating a wrapper function which always runs the original function with .call and our specific object we’re throwing away whatever the sayHello.call specifies. This way we can always be sure that the this keyword is referencing what we want.

In ECMAScript 5 we have the built in function bind that is specified on Function.prototype to help us with hard binding.

function sayHello() {
	console.log(this.name);
}

var person1 = {
	name: "Jonathan"
};

var name = "Kalle";

setTimeout(sayHello, 1000); // undefined
setTimeout(sayHello.bind(person1), 1000); // Jonathan

The setTimeout function will have it’s thisBinding pointing at the global/window object which is the last of the four rules(Default binding, explained below). But with hard binding we force the thisBinding to point the object we want.

Implicit binding

The third rule is the implicit binding. The rules states that the containing object is referenced by the this keyword when a function is called.

function sayHello() {
	console.log(this.name);
}

var person1 = {
	name: "Jonathan",
	sayHi: sayHello
};

var person2 = {
	name: "Kalle",
	sayHi: sayHello
};

person1.sayHi(); // Jonathan
person2.sayHi(); // Kalle

As we can see above it doesn’t matter were the function was declared only how it was called. So when sayHi was called with person1.sayHi the this keyword is referencing person1 and on the line under it’s referencing person2.

var personUtilities = {
	sayHello: function() {
		console.log(this.name)
	}
};

var person1 = Object.create(personUtilities);
person1.name = "Jonathan";


var person2 = Object.create(personUtilities);
person2.name = "Kalle";

person1.sayHello(); // Jonathan
person2.sayHello(); // Kalle

The same is true for functions in the prototype chain no matter how high up they’re defined.

The implicit binding is all about finding the nearest object and then you’ll know what this is a reference to.

Default binding

The last catch-all rule is the default binding.

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

var name = "Jonathan";

sayHello(); // Jonathan, true

If none of the other three rules above matches the default binding kicks in. The example above shows us that this is referencing the global/window object in the sayHello function.

function sayHello() {
	"use strict";
	console.log(this === undefined)
}

var name = "Jonathan";

sayHello(); // undefined

If strict mode is specified inside the function the global/window object is not eligible for the default binding. If the call-site is running in strict mode but not the executed function this will reference the global/window object.

var person = {
	name: "Jonathan",
	sayHello: function() {
		console.log(this.name);
	}
};

var sayHi = person.sayHello;


sayHi(); // undefined

Remember that it’s all about the call-site. In the above code we created a variable sayHi and referenced person.sayHello. Then we called sayHi without an object in front of it so the default binding rule applies and in this case the global/window object doesn’t have variable called name and therefore we get an undefined error.

Arrow functions

Until arrow functions was introduced in ECMAScript 6 every function defined it’s own this reference. Arrow functions lexically binds this. Meaning that this will be the same as in it’s enclosing context.

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

	setTimeout(function() {
		console.log(this.name); // undefined
		console.log(this === window); // true
	}, 1000);
}

var person = new Person("Jonathan");

Without a normal callback function the default binding will apply and this will be the global/window object.

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

	setTimeout(() => {
		console.log(this.name); // Jonathan
	}, 1000);
}

var person = new Person("Jonathan");

But with a arrow function this will be the same as in the enclosing context.

setTimeout(() => {
	"use strict";
	console.log(this === window); // true
}, 1000);	

In the above code this is referencing the window object even though were using strict mode because this is lexically bound.

Conclusion(tl;dr)

The this keyword in JavaScript can be confusing but when you learn the four binding rules it’s quite straightforward. It’s all about how and where the function was called.

We have the new binding which happens when the new keyword is put in front of any function. It creates an empty object and binds this to it inside that function.

The explicit binding with .call and .apply which makes it possible to call a function with a specified object as this.

The implicit binding that states that it doesn’t matter where a function was declared only where it was called. Find the call-site and on which object the function was called. If obj.sayHello() was called, then inside sayHello this would point to obj.

The default binding which is the catch-all rule binds this to the global/window object(in strict mode it will be undefined) when none of the other three rules apply.

Arrow functions introduced in ECMAScript 6 is the exception to these rules above. It uses a lexical this which means that this will be the same as this in the enclosing context.

JavaScript series: Prototype-based inheritance

JavaScript does not have classes so when we’re talking about prototypes try not to think about classes. This can be very confusing for developers who come from a class oriented language like C# or java. JavaScript is truly an object oriented language. All objects in JavaScript are descended from the “root object” called Object. The prototype itself is an object that exists as a property on all objects and it’s what’s used to implement prototype-based inheritance and shared properties. By default a newly created object has a prototype that is a reference to Object.prototype.

The prototype chain

Let’s create a new object.

var obj = {
	myFunction() {
		console.log(1);
	}
};


console.log(obj); // { myFunction: [Function: myFunction] }

console.log(obj.toString()) // [object Object]

console.log(obj.hasOwnProperty("myFunction")); // true

console.log(obj.hasOwnProperty("toString")); // false

First we created an object called obj with the object literal syntax. When we log the object to the console we can see that it has a function named myFunction. But somehow obj.toString() references a function that prints [object Object]. I’ve then used a function called hasOwnProperty which is also not defined on obj which prints true for myFunction but prints false for hasOwnProperty. So where does these functions come from now that we can that they’re clearly not defined on obj.

This is where the JavaScript prototype object comes in. When calling obj.toString() and obj does not have that property it will try and go to it’s prototype and look for it. In our case obj’s prototype will be a reference to Object.prototype which is the default for created objects. When it came to Object.prototype it found a property named toString and used that. This is how the prototype works. JavaScript will traverse up the prototype chain until it finds the property it’s looking for or if the prototype is null which the prototype of Object.prototype is.

So what do the hasOwnProperty() function tell us. This description is from developer.mozilla.org

Returns a boolean indicating whether an object contains the specified property as a direct property of that object and not inherited through the prototype chain.

This means that obj doesn’t own the toString function and is only accessible because of how the prototype works.

The new keyword and creating a prototype

var obj1 = {
	aFunction: function() {
		return 1;
	},
	aProperty: 123,
}

function Obj2() {

}

Obj2.prototype = obj1 // Assign obj1 as the prototype of Obj2

var obj2 = new Obj2(); // Create a new empty object and set it's prototype to reference Obj2.prototype

console.log(obj2); // {}

console.log(obj2.aFunction()); // 1
console.log(obj2.aProperty); // 123

console.log(Object.getPrototypeOf(obj2) === Obj2.prototype); // true
console.log(Object.getPrototypeOf(obj2) === obj1); // true
console.log(Object.getPrototypeOf(obj2).__proto__ === Object.prototype); // true

In the above code we created an object called obj1 with a function and a property with an integer value. Then we created a function object called Obj2 and sat it’s prototype to reference object obj1. On line fourteen we used the new keyword in front of the Obj2 function call. This is where it can get confusing coming from a class oriented language. When the new keyword is put in front of a function call it creates an empty object and assigns it to the this keyword it then magically returns the new object. In this case it sets it’s internal prototype reference to Obj2.prototype which in turn references the obj1 object. The obj1 objects internal prototype references Object.prototype. So now we have access to properties and functions in both object obj1 and Object.prototype through the prototype chain.

The Object.getPrototypeOf was standardized in ECMAScript 5 and gets the prototype of an object. The __proto__ property pronounced “dunder proto” is standardized in ECMAScript 6 but exists in most browsers today but it’s behavior is not standardized in earlier versions of ECMAScript. If you only want to read the prototype, Object.getPrototypeOf and __proto__ achieves the same thing.

It’s important to understand that JavaScript does not make copies of prototypes when a new object is created. Prototypes are only references to other objects.

function Obj1() {
	this.sayHello = function() {
		console.log("Obj1 said hello");		
	}
}

Obj1.prototype.sayHello = function() {
	console.log("Obj1 prototype said hello");
}

var obj1 = new Obj1();

obj1.sayHello(); // Obj1 said hello
Object.getPrototypeOf(obj1).sayHello(); // Obj1 prototype said hello
console.log(Object.getPrototypeOf(obj1) === Obj1.prototype) // true
console.log(obj1.hasOwnProperty("sayHello")); // true

First let’s repeat again what the new keyword does. It creates an empty object and assigns it to the this keyword. The prototype of the newly created object gets linked to the prototype of the function which was called with new keyword in front of it and then returns the object. Here we created a function called sayHello on the newly created object which is then assigned to the object called a. We also created a function called sayHello on the prototype object of A. What’s happening now when we call a.sayHello() is that it finds a function named sayHello directly on object a and will therefore not traverse the prototype chain. This is called shadowing. We can still access our prototypes version of sayHello by referencing the prototype object.

Object.create vs new

The object.create function is available since ES5. This is what the ECMAScript specification says about the Object.create function:

Object.create ( O [ , Properties ] )

The create function creates a new object with a specified prototype

function Obj1() {
    this.sayHello = function() {
        console.log("Obj1 said hello");
    }
}
 
Obj1.prototype.sayHello = function() {
    console.log("Obj1 prototype said hello");
}
 
var obj1WithNew = new Obj1();
var obj1WithCreate = Object.create(Obj1.prototype);
 
obj1WithNew.sayHello(); // Obj1 said hello
console.log(obj1WithNew.hasOwnProperty("sayHello")); // true
obj1WithCreate.sayHello(); // Obj1 prototype said hello
console.log(obj1WithCreate.hasOwnProperty("sayHello")); // false

Here we can see that when using the new keyword we always have to run the constructor call to create a new object. But with Object.create we get an empty object without making a constructor call. The object1WithCreate object does not have a property named sayHello which the ECMAScript specification explained above.  To further explain Object.create let’s look at this simple polyfill without the second parameter.

Object.create = function(o) {
	function F() {}
	F.prototype = o;

	return new F(); 
};

The polyfill creates an empty object with a constructor call that does nothing and assigns the prototype to the passed in object before returning it.

As we can see Object.create makes inheritance in JavaScript simpler.

Conclusion(tl;dr)

JavaScript is an object-oriented language with prototype-based inheritance. When a property is not found on the current object it will traverse the prototype chain until it finds the property or reaches the top(when that prototype objects prototype is null).

The new keyword can be placed in front of any function call which makes JavaScript create an empty object and sets it’s prototype to reference the called functions prototype.

Shadowing is when a property is specified further down the prototype chain which hides a property with the same name higher up.

Object.create is used to create an empty object with a specified prototype without making a constructor call.