Quantcast
Channel: Generated Content by David Storey
Viewing all articles
Browse latest Browse all 65

Variables and Constants in ES6

$
0
0

The humble var keyword has been with us since the very beginning of JavaScript. With ECMAScript 6, we’re gaining new ways to declare variables and even constants. Now that browser support is starting to improve, I’d like to take the opportunity to run through what we have now, what is coming up on the horizon.

If you have any experience with JavaScript, you probably know at least something about variables and scope. You’ll know that to define a variable you use the var keyword:

var aNewVariable = null;

You’ll probably also know that a variable is in the global scope if declared outside of a function, and the local scope if declared inside a function:

var globalVariable = "Global";

function aFunction() {
	var localVariable = "Local";
}

What may confuse you at first, if you come from a background in C-like languages–such as Java–is that local variables in JavaScript have function scope, rather than block scope. That is, variables behave as if they are hoisted up to the top of the function. Variables defined in a block, such as the body of an if statement, can be accessed from the enclosing function. They can even be accessed before the variable is declared:

function aFunction() {
   // sets the variable defined in the do/while block
   blockVariable = "Not global";
    
    do {
        var blockVariable = 1;
    } while (false);
    
    // 1 as can access variable inside block;
    console.log(blockVariable); 
}

While this slightly confusing behaviour can be useful, block level scope also has its place. Previously, there was no way to achieve this in JavaScript, except applying “hacks” such as including the code you want to be block level inside a self executing function. With ECMAScript 6 (ES6 for short), that will change, with the introduction of the let keyword.

Block level scope with let

Variables declared with the let keyword work in a similar way to those declared with var, except they use block level scoping instead of function level. If we adapt the previous example to declare blockVariable with let, and run it in browser that supports the keyword (more on that below), you’ll see that two different variables will exist: one inside the do/while block, which has block level scope, and a global property (it isn’t exactly a variable) outside of the block.

function aFunction() {
   // creates new property on the global object
   blockVariable = "property of the Global object";
    
    do {
        let blockVariable = 1;
    } while (false);
    
    // "property of the Global object" as can’t access variable inside block;
    console.log(blockVariable); 
}

One place where let seems immediately useful is when initialising a for loop. Due to variable hoisting, it is often recommended to define your initialiser (often called i) at the top of the function. However, this divorces the variable from the loop somewhat, and it personally feels a bit strange. Using let will give you the best of both worlds:

for (let i = 0; i & 10; i++) {
	//do stuff
}
As with anything ES6, browser support is where things fall a bit flat at the moment. IE11 has just implemented it by default. Firefox has had let for a long time, but you have to enable JavaScript 1.7 mode (let was formally Firefox specific) using type="application/javascript;version=1.7". With it becoming more common practice to remove the type attribute when using HTML5, this feels a little odd now, but I’m sure this requirement will change as ES6 matures.

For Chrome, things are a little more tricky. First you need to enable experimental JavaScript features in ”chrome://flags/”. Then it seems to only work if you are using strict mode: "use strict"; as the first statement of the script or function. It is not supported in Safari or Opera (technically, it would be supported in Opera 15 if you enable the experimental flag, but there is currently no way to do this).

Declaring constants with const

As well as variables, many languages have the concept of constants. That is, variables where you can not change the value once it has been initialised. JavaScript lacks this ability, although if you have an object, you can freeze it using Object.freeze in ES5.

With ES6, we will get this ability directly with the new const keyword. As you would expect, once you have declared a const, the value can’t be changed:

(function () {
	const CONSTANT_VARIABLE = "Foo";

	/* should print "foo" to console */
	printValue(CONSTANT_VARIABLE);
	
	/* Try to change value. Should fail */
	CONSTANT_VARIABLE = "Bar";
	
	/* should still print "Foo" to console, not "Bar" */
	printValue(CONSTANT_VARIABLE);

	function printValue(val) {
    		console.log("Value of CONSTANT_VARIABLE is " + val);
	}
})();

You’ll notice I’ve made the identifier all uppercase in the example above. I prefer to name constants this way, as it is consistent with how constants are named in host and native objects.

One thing to be aware of with const in ES6 is that they share the same block level scoping as let. This is different from how they were originally defined in JavaScript 1.7, and implemented in Firefox, where they have function scope, the same as var. IE11 uses block level scoping, as does Chrome, but only when you use strict mode and enable the experimental flag. Unfortunately, Opera, Safari, and Chrome without the flag only support const if you don’t use strict, so support is mutually exclusive here.

The other thing you should be aware of is that Presto-based Opera and Safari 6 both support const but treats it exactly like var. That is, it isn’t a constant at all; you can change the value. I’ve not managed to test Safari 7, but the latest WebKit nightlies work as in the ES6 spec.

Browser support

As mentioned, the key drawback of using const and let is the browser support. Until older browsers die out and flags get enabled by default, the keywords are mostly just useful when making installable apps that target certain platforms; such as FirefoxOS or Windows 8.1 apps.

The table below shows the current support level for the last release and nightly/preview release of the 5 major browsers. As there is various levels of support for const, I’ve broken it down into three rows: if variables can be declared using the const keyword without throwing an error, if the value stays constant, and if they have block level scope. If only the first is supported, the browser treats a const the same as a regular var.

FeatureIE 11IE 10FirefoxChromeOpera 15Opera 12.1WebKit NightlySafari 6
letYesNoJS 1.71Flag2/strict3NoNoNo
recognise constYesNoYesYes, !strict4!strict4!strict4
constant constYesNoYesYesNoYesNo
block level constYesNoNoFlag2/strict3NoNoNo

Compatibility notes

  • Firefox currently needs to be in JavaScript 1.7 mode to support let. This can be enabled by using type="application/javascript;version=1.7" on the script element.
  • Chrome requires experimental JS features to be enabled.
  • Only supported when in strict mode: "use strict";
  • Chrome without experimental JavaScript enabled, Safari, and Opera only supports const when not in strict mode. When experimental features are enabled, Chrome supports const both in regular and strict mode.
Note: I’m much more comfortable with HTML and CSS than ECMAScript, so please forgive me if I’ve made glaring errors, or terminology mistakes. Please let me know and I’ll update accordingly.

Viewing all articles
Browse latest Browse all 65

Trending Articles