ES6: Constant and block scoped variables

Constant

In javascript we can’t declare a variable as constant. But we can achieve it by using Object.defineProperty()

This method accepts three arguments: the object on which the property should be added or modified, the name of the property, and a descriptor object. The properties on the descriptor object match the attribute names: configurable, enumerable, writable, and value.

[[Configurable]] — Indicates if the property may be redefined by removing the property via delete, changing the property’s attributes, or changing the property into an accessor property.

[[Enumerable]] — true if and only if this property shows up during enumeration of the properties on the corresponding object.

[[Writable]] — Indicates if the property’s value can be changed. By default, this is true for all properties defined directly on an object.

[[Value]] — Contains the actual data value for the property. This is the location from which the property’s value is read and the location to which new values are saved. The default value for this attribute is undefined.

So to create a constant,  declare a global variable which will be part of global or window object  which value can’t be changed or alter or deleted.

Object.defineProperty(typeof global === "object" ? global : window, "PI", {
    value: 3.141593,
    enumerable: true,
    writable: false,
    configurable: false
});
PI => 3.141593

 

ES6 introduce const to declare constant which can’t be altered, deleted or re-declared.

const PI = 3.141593

PI => 3.141593

 

const VERSION = 2.0;

// this will throw an error
VERSION = 2.3;

// will print 2.0
console.log(VERSION);

// trying to redeclare a constant throws an error
const VERSION = 2.7;

// the name VERSION is reserved for constant above, so this will also fail
var VERSION = 3.0;

 

Block scoped variable

ES6 introduce a new keyword let to declare block scoped variable.  Let’s see the difference between var and let

function varTest() {
    var x = 1;
    if (true) {
        var x = 2;  // same variable!
        console.log(x);  // 2
    }
    console.log(x);  // 2
}

 

function letTest() {
    let x = 1;
    if (true) {
        let x = 2;  // different variable
        console.log(x);  // 2
    }
    console.log(x);  // 1
}

 

More Examples

var callbacks = [];
for (var i = 0; i <= 2; i++) {
    callbacks[i] = function() { return i * 2; };
}

callbacks[0]() => 6
callbacks[1]() => 6
callbacks[2]() => 6

 

This one is the classic example of closures. When all functions get called that time i reached to maximum value 3. To avoid this we use anonymous function.

var callbacks = [];
for (var i = 0; i <= 2; i++) {
    (function (i) {
        callbacks[i] = function() { return i * 2; };
    })(i);
}

callbacks[0]() => 0
callbacks[1]() => 2
callbacks[2]() => 4

 

In above example we handle closure and passed i as a parameter to the anonymous function and i became local inside that function.

In ES6 we can do it without handling closure by declaring in blocked scope

var callbacks = [];
for (let i = 0; i <= 2; i++) {
    callbacks[i] = function() { return i * 2; };
}

callbacks[0]() => 0
callbacks[1]() => 2
callbacks[2]() => 4

 

Leave a comment