Skip to content

Instantly share code, notes, and snippets.

@jefflau
Last active October 3, 2015 09:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jefflau/193c2079967901176600 to your computer and use it in GitHub Desktop.
Save jefflau/193c2079967901176600 to your computer and use it in GitHub Desktop.
A journey through ES6 - Part 1

A journey through ES6 - Part 1

I’ve just started learning ES6 properly and to help others I’m going to document what I’ve learnt through a series of blog posts. In this post we’re going to start with the most basic parts of ES6 that you can jump into straight away. let and const are two new keywords for defining variables. Both are really simple to use and solve some problems in the JavaScript language. 

##let

We’ll start looking at let first. JavaScript’s scoping is done with functions. That means anything declared as a var inside a function closure will be only accessible within the function. One thing JavaScript didn’t have before ES6 was block scoping, and that is where let comes into play. Block scoping is scoping within a ‘block’. That block is denoted by the { ... } curly braces in JavaScript.

let allows you to create block scopes

{
  let x = 2 
}
console.log(x) //undefined

You might find the syntax of { ... } within an if statement or for loop a little strange, but it always has been valid JavaScript, albeit a little useless without block scoping, but it is more commonly used in other languages.

let is most useful in a for loop, where the counter variable is declared for each iteration of a loop, so you don’t get issues with callback functions where the callback hasn’t been called yet, and so it uses the last iteration of the loops value.

var array = [1, 2, 3]; 

for (var i = 0; i < array.length; i++) { 
  setTimeout(function () { console.log(array[i]) }, i * 1500); 
};

Here, because of the setTimeout the output by console.log(array[i]) will be undefined, because by the time the setTimeout callback is run, the value of i is already 4.

Another example of this scoping problem is as follows:

var funcs = [];

for (var i = 0; i<5; i++) {
  funcs.push(function(){
    console.log(i)
  });
}

funcs[1]();
//5

In the same way as the last example, because of the scoping of var, there isn't a new variable created for each and every iteration of the loop, so when the funcs[1] is called, the value of i is already 5.

Both of these previous examples can be fixed, by replacing the var with let. The reason for this is that let creates a new scope for every iteration of the loop, and therefore when it is called for later on, it is the value it was when that iteration of the loop took place. It's a little confusing in theory if you've never run into this problem before, and you would have to use function closures to get around this deficiency in the language before the let keyword, but all you need to remember is to use let in for loops to get expected behavior.

var funcs = [];

for (let i = 0; i<5; i++) {
  funcs.push(function(){
    console.log(i)
  });
}

funcs[1]();
//1

To illustrate how awesome let is. The code below is how you would normally create a closure per iteration. Every iteration of the loop the statement to push the new function into the array is wrapped in an IIFE (Immediately Invoked Function Expression) to create a new scope for the argument j that is actually just the variable i being passed through the IIFE. Explaining the issues of a lack of block scope is out of the scope of this article (get it?!), but it's always been a mouthful to write if you need to get around this deficiency in the language. Now that we have let, we can write cleaner easier to understand code.

var funcs = [];

for (var i = 0; i<5; i++) {
  (function(j){
    funcs.push(function(){
      console.log(j);
    });
  })(i);
}

funcs[1]();
//1

####Temporal Dead Zone

If you declare the let variable after you call it, you'll get a ReferenceError as it is only initialised when you get to the let keyword. If you did the same thing with var, the variable declaration is actually hoisted to the top, so you would get undefined. In short let is not hoisted

##const

const is a little more simple than let. It allows you to create what we've stylistically been creating for years with ALL CAPS variables such as:

var TRANSITION_INTERVAL = 5000;

This can be simply written as:

const TRANSITION_INTERVAL = 5000;
TRANSITION_INTERVAL = 2000
//TypeError!

const will not let you change a primitive value such as numbers or strings. It is not a restriction on the value itself, but of the variable's assignment of that value. That means that you will be able to mutate an object, by changing a current property or even adding a new one.

const TRANSITION_DATA = {
  interval: 5000
}

TRANSITION_DATA.interval = 2000;
TRANSITION_DATA.type = 'fade';

TRANSITION_DATA.type; // 'fade'
TRANSITION_DATA.interval; // 2000
@hiddentao
Copy link

Errata:

  • setTimeout the value of i will be undefined - should be array[i]
  • declared as a var inside a function - use code font var

For const also note that declaring it as such enables the VM to perform some optimisations for it, thereby potentially speeding up execution.

@Huanzhang89
Copy link

so when using const to define objects you can reassign the value of properties but cannot define new properties on the object?

@jefflau
Copy link
Author

jefflau commented Sep 7, 2015

@Huanzhang89

You can mutate the object however you like, it doesn't stop you from mutating current properties on the object or defining new ones so you could do:

const obj = {
  a: 2
}

obj.b = 3;

console.log(obj.b);  //3

@Huanzhang89
Copy link

so whats the difference? Thats the same as doing

var obj = {
  a: 2
}

obj.b = 3;

console.log(obj.b); //3 

So whats the benefit of using const for object declarations?

@jefflau
Copy link
Author

jefflau commented Sep 7, 2015

@Huanzhang89

As far as I can tell, nothing. The only difference is that you can't do this:

const obj = {
   a: 2
}

obj = 2; //TypeError!

Basically I'd just keep it to primitive types, so just numbers, strings and booleans and leave it at that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment