The const keyword is another addition in ECMAScript 6 (ES6). This one can be a bit confusing depending on the tools you were using only because const has been around not as part of any official ES language specification but the V8 Engine has recognized a const keyword for sometime so you might have seen it used in Chrome or Firefox. But the idea is as the name suggests to create and initialize a read-only variable. A variable that will hold a constant value and something that you can never change. In ES6 const will have block scoping just like the let keyword. Let’s take a look at this in a test.
describe("using const",function(){
"use strict";
it("will make a variable read-only", function(){
const MAX_SIZE = 10;
// MAX_SIZE = 12; // SyntaxError
expect(MAX_SIZE).toBe(10);
});
});
Inside my test, I am using const to declare a variable named MAX_SIZE setting its value to 10. I expect MAX_SIZE to be 10 and off course the above test currently passes.
describe("using const",function(){
"use strict";
it("will make a variable read-only", function(){
const MAX_SIZE = 10;
MAX_SIZE = 12; // SyntaxError
expect(MAX_SIZE).toBe(10);
});
});
However, if I try to assign MAX_SIZE a value of 12, the test fails. It throws a TypeError: Assignment to constant variable. This represents the semantics of true ES6 const. There will be an error if you try to assign to a const and that’s a little bit different than the const that has been around in browsers like Chrome and Firefox. What they would do is allow you to assign to a const but effectively ignore the value. They wouldn’t throw an error but they also wouldn’t change the value of that variable. In ES6 it is an TypeError.
The following code snippets will demonstrate couple of things. First, const does have block semantics and second how both let and const work when you have multiple variables with the same name.
it("can shadow outer declaration",function(){
var doWork= function(){
var x = 12;
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
});
Currently, the above test has 2 lines of code inside of doWork that declare a variable x and this perfectly legal JavaScript. Running this test will result in a Pass since the value that is returned from doWork is 10. Now what if we change x to a const as done below.
it("can shadow outer declaration",function(){
var doWork= function(){
const x = 12;
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
});
Running the above test, throws an Uncaught SyntaxError: Identifier ‘x’ has already been declared in the browser’s console and that’s another difference between let and const versus var because with let and const we cannot have two variables inside of the same scope that have duplicate names. If const is changed to a let as shown below we get the same error – Uncaught SyntaxError: Identifier ‘x’ has already been declared in the browser’s console.
it("can shadow outer declaration",function(){
var doWork= function(){
let x = 12;
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
});
However, if we move let x = 12 outside of doWork, and run the test, then my test Passes. That’s because the x that is defined inside of doWork is hiding or shadows the x that is defined outside of that function. Inside of doWork I am working with a variable x that holds the value 10.
it("can shadow outer declaration",function(){
let x = 12;
var doWork= function(){
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
});
But outside of doWork I can be working with a variable x that holds the value 12 and so when I am assigning x inside of doWork I am not writing into that outer x.
it("can shadow outer declaration",function(){
let x = 12;
var doWork= function(){
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
expect(x).toBe(12);
});
Changing let to const in the test also passes the test since const x = 12 is defined in a different block, a different scope.
it("can shadow outer declaration",function(){
const x = 12;
var doWork= function(){
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
expect(x).toBe(12);
});
To demonstrate const has a block scoping,
it("can shadow outer declaration",function(){
if(true){const x = 12;}
var doWork= function(){
var x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
expect(x).toBe(12);
});
wrapping const x = 12 in an if block and running the test results in a failure with an error message of ReferenceError: x is not defined.
Finally, the inner x will also work if var was replaced with a let.
it("can shadow outer declaration",function(){
if(true){const x = 12;}
var doWork= function(){
let x = 10;
return x;
};
var result = doWork();
expect(result).toBe(10);
expect(x).toBe(12);
});