A solution to ‘var self = this’
A common situation in javascript is needing to access a property or method of the parent scope object within a closure. To solve this, we declare a variable referencing the parent scope, and then access the desired property or method using that variable within our closure. Consider this example:
class Pizza { constructor(name toppings) { this.name = name; this.toppings = toppings; this.availableMeats = ['Chicken', 'Pepperoni']; } getMeatToppings() { var self = this; return this.toppings.filter(function(topping){ return (self.availableMeats.indexOf(topping) > -1); }); } }
Notice the var self = this in the Pizza.getMeatToppings method. ES6 introduces a way to declare functions that don’t create an isolate scope. You can declare a method using an arrow function instead of the function keyword:
class Pizza { constructor(name toppings) { this.name = name; this.toppings = toppings; this.availableMeats = ['Chicken', 'Pepperoni']; } getMeatToppings() { return this.toppings.filter((topping)=>;{ return (this.availableMeats.indexOf(topping) > -1); }); } }
Notice the way Pizza.getMeatToppings() is declared with => instead of function. This new syntax is called an arrow function.
Block scope in ES6
Variables in ES5 can be in two scopes — function scope or global scope. ES6 introduces a new way to declare variables in block scope using the let keyword.
getData().then(function(response){ if (response.status == 'OK') { var data = response.data; /* do stuff with data */ } });
In the example above, the data variable is often treated as if it its scope is the if block — when the variable is actually function scoped. The actual scope looks something like this:
getData().then(function(response){ var data = undefined; if (response.status == 'OK') { data = response.data; /* do stuff with data */ } });
This is called hoisting. When a variable is declared, the declaration is ‘hoisted’ to the top of the current scope.
Declaring block scoped variables with let
ES6 introduces a new way to define variables using the let keyword instead of var. Variables declared with var are function scoped — and variables declared with let are block scoped. We can revise the above example to make the data variable scoped to the if block, by using the let keyword:
getData().then(function(response){ if (response.status == 'OK') { let data = response.data; /* do stuff with data */ } });
In the revised code, the data variable is scoped to the if block. The let keyword can be used to bind variables to the scope of a for loop:
for (let i = 0; i < 10; i++) { console.log(i); // > 1, 2 ... 9, 10 } console.log(i); // > undefined
Declaring constants with const
Another new keyword for variable declaration in ES6 is const. Variables declared with const represent a constant reference to a value. The value being referenced may changed, but the value cannot be reassigned. Here’s an example:
const languages = ['English', 'Spanish']; data.push('French'); console.log(data); // > ['English', 'Spanish', 'French'];
The above example will print out the languages array, including the item we pushed. If we try to assign the constant to a new array, an error is thrown:
const languages = ['English', 'Spanish']; languages = []; // -> Error
There’s a lot of confusion surrounding scope in javascript. With the advancements brought by ES6, scoping will become more manageable.