Intro to ES6 functions

Despite ES6/ES2015 (or ES2016 now) not being officially released, it is very much in use at the moment through the use of different packages and varying levels of support in node.js and other frameworks. A quick google search for “Introduction to ES6” will net a lot of results about the upcoming functionality of ES6, a lot of it quite technical. This post is simply to reinforce at a very basic level, some of the major incoming changes.

The main contender for allowing web developers to make use of ES6 is babel.js. Babel is incredibly helpful in transforming ES6 code back into browser-supported ES5 code. The babel website also includes what is a much more detailed version of what I’m going to write here, which is their learn ES 2015 page which I would suggest reading over if you’ve got more time. One more thing to note regarding babel is that it supports JSX, the file type popularised by the React.JS framework.

This post is going to go over some of the key features included in ES6 to act as a cheatsheet if you come across some code that you don’t recognise, and to help you understand it in terms of ES5. This post will not cover every new feature coming in ES6, but those which I’ve used and I expect will see a lot of use in the future. For a full list of changes coming in ES6, take a look at the further reading section at the bottom of this post.

Arrow function expressions (or Fat Arrow function):

An arrow function expression is a shorthand version of function expressions found in ES5. If you’ve used coffeescript in the past, this will look quite familiar to you. Here is an example of the new syntax:

(param1, param2) => {
  // code
}

which would look like this in ES5:

function(param1, param2) {
  // code
}

One important difference when making use of an arrow function is that it will share the same lexical this as the environment it was called from which means in this example –

var person = {
  name: "Mike",
  favouriteNumbers: [1,2,3],
  showNumbers() {
    this.favouriteNumbers.forEach(num =>
      console.log(num +
                  " is one of " +
                  this.name +
                  "'s favourite numbers!");
    }
  }
}

– this.name is still accessible within the forEach arrow function as a reference to the person object’s name property.

Template Strings:

Template strings provide syntactic sugar for constructing strings. If you’re familiar with other languages, you will have seen string interpolation before which allows you to place a variable directly inside of a string between special symbols.

Previously in JavaScript, combining variables with strings could be accomplished by:

var name = "Mike";
console.log("Hello, " + name);

This method can get a bit messy when you’ve got a lot of strings and it can be a bit prone to error when you have a lot of different quotation marks to handle. The ES6 way to do this looks like:

var name = "Mike";
console.log(`Hello, ${name}`);

Notice that the entire string is contained within backticks as opposed to other type of quotations.

Although there are more use-cases for template strings, another interesting feature I found interesting is the ability to create multi-line strings like this:

`This is not
legal in ES5`

Module importing:

A feature that is very common in node.js and other languages is the ability to import code from different files into our main JavaScript files. This allows us to separate concerns to a greater extent and create reusable modules allowing us to focus on writing well-structured, decoupled code. Here is an example of this idea:

// greeting.js

export function greet(name) {
  console.log(`Hello, ${name}!`);
}

and then in another file:

// app.js

import { greet } from 'greeting.js';
greet("Mike");

Running the app.js file will output “Hello, Mike!”.

Import is incredibly powerful and flexible in terms of what you want to import. I may write a future post about the full extent to which import can be used in future, however if you’d like to know more now, check out the MDN page on import.

Let declarations:

Let declarations are a new way to declare a variable and in practice behave very similarly to var. The main difference is that the scope of a var variable is the entire enclosing function as illustrated in the examples below:

In a global context, these declarations are identical:

var x = 1;
let x = 1;

In a functional context, these are again identical:

function exampleFunction() {
  let x = 1;
  var x = 1;
}

In a block context, let is only available inside the code block that it is declared to be part of:

function exampleFunction() {
  for (let i = 0; i < 5; i++) {
    // i is only available here.
  }
}

Whereas if you use var:

function exampleFunction() {
  // i is available here.
  for (var i = 0; i < 5; i++) {
    // i is available here.
  }
  // i is available here.
}

Const Declarations:

A const declaration allows you to assign a value to a namespace which you are telling the program that the value will not change. One thing that can be sometimes confusing is that this does not mean the const is immutable. If you assign an object with Const, it is possible to change the properties of that object, the better way to think of const is that it can’t be reassigned to anything else. When declaring new constants, it is common practice for the name to be written in full capitals. Here are some examples to illustrate how this works:

const X = 1;
X = 10;
// this reassignment is illegal and will produce an error

Here is the object example I outlined above:

const PERSON = {
  name: "Mike"
}

PERSON.name = "John";
// this property reassignment is legal

PERSON = {
  name: "John"
}
// this reassignment is illegal because it's
// pointing the const at an entirely new value.

In practice, const is one of the clearest declarations to use throughout code. It makes the entire application a lot easier to read as you will always know what a const is referring to throughout the course of the application. For a further discussion on in practice use of var, let and const, I’d recommend Eric Elliot’s post on the matter.

EDIT: One thing I failed to mention before was that although it’s possible to make somewhat mutable objects through const. Through use of the Object.freeze({objectName}) method. Given that one of the major reasons to use a constant is to create a variable that can not be reassigned or changed, it should be considered best practice when dealing with object constants to use freeze on them. Here is how the objects should be declared:

const OBJECT = Object.freeze({
  prop: val,
  anotherProp: val2
})

Promises:

Promises give you the ability to handle callbacks in a different way by waiting for a response from an asynchronous operation and running a block of code in a .then() block afterwards. I’ve covered Promises in more detail recently and you can read about them here:

Promises Part 1 – Asynchronous Code
Promises Part 2 – Promise Definition
Promises Part 3 – Using the Q Library

More to come:

There are a lot more new features coming in ES6 which I want to cover in more detail in their own posts, such as Generator functions and ES6 Classes (caution: more in common with typical JS Prototypal inheritance than OOP based classes). I will come back to modify this post as I create new posts about these features.

Hopefully this post has given you a basic introduction to some of the upcoming changes in ES6 and how they work. If you’ve got any specific features that you’re looking forward to in ES6, leave a comment below to let me know about it!

Further Reading:

Brief Overview of ES6 Module syntax
ES6 features – An overview and comparison of new features
Luke Hoban’s ES6 features overview
Eric Elliott on var, let and const
Official ES2015 Overview

Advertisements

Promises – Part 2 – Promise definition

Hopefully part 1 made it clear why promises can be useful in an asynchronous language like JavaScript. I think it’d now be best to talk a bit more about what a promise is and how exactly it works.

A promise is an object that defers a future state in the same way a callback can be used and is a cleaner alternative. To clarify what I mean by cleaner, there is a concept in programming known as “Callback Hell” which describes when functions become nested and difficult to read through the use of callbacks, here’s an example:

a(function (resultFromA) {
    b(resultFromA, function (resultFromB) {
        c(resultFromB, function (resultFromC) {
            d(resultFromC, function(resultFromD) {
                console.log(resultFromD);
            })
        })
    ))
});

You probably get the idea that with more complex functions, this can get messy fast! (Check out callbackhell.com for a more thorough explanation)

Returning to what a promise is, a promise is a placeholder object that represents the result of an asynchronous operation. It holds the current status of the operation and can notify us when the operation either succeeds or fails. A promise can exist in three different states:

  • Pending – the promise’s outcome hasn’t yet been determined, because the asynchronous operation that will produce its result hasn’t completed yet.
  • Fulfilled – the asynchronous operation has completed, and the promise has a value.
  • Rejected – the asynchronous operation failed, and the promise will never be fulfilled. In the rejected state, a promise has a reason that indicates why the operation failed.

(These definitions were taken from Spring.IO)

The only state that a promise can change from is pending to either fulfilled or rejected and once it reaches that point, it can not change again.

Promises have a .then() method which can be used to handle the eventual result of the operation and takes one parameter as a function to execute after the promise has resolved.

In the event that a promise is rejected, a .catch() method can be used as an error handling function, like so:

promiseValue.then(function(value) {
    console.log(value);
}).catch(function(error) {
    console.log("There was an error", error);
});

The .then() method returns another promise which means it is possible to chain this method resulting in a chain of promises without having to nest the functions and avoiding the problems we would face with a series of callbacks.

Promises can be created using new Promise which then takes a function. This function takes two parameters: resolve and reject. These are methods that signify the promise is fulfilled. Any errors should be passed to reject(). Data that has been successfully retrieved should be passed to resolve(), if you need to use it. Otherwise, you can call resolve() with nothing passed in if this does not matter. Here is an example using the ES6 version of promises for how this would look:

var promiseValue = new Promise(function(resolve, reject) {
    asyncFunctionWithCallback(function(err, data) {
        if (err) return reject(err);
        return resolve(data);
    });
});

 

Promises are being introduced as first-class language features in ES6 and alternatively there are different JavaScript libraries which can handle promises such as Q, RSVP, when or even jQuery. I’ll begin looking at these libraries in the next post.

Thanks for reading! If you’ve got any comments, I’d love to hear from you.

Promises:

Further reading:

Promises – Part 1 – Asynchronous Code

Before I get stuck in to explaining promises, there’s another programming concept I need to go over first; synchronous and asynchronous code. The JavaScript language is asynchronous, which means that it is possible for a block of code to continue running while an asynchronous call is made. Here is a block of JavaScript to help illustrate this concept:

console.log("First");
setTimeout(function() {
    console.log("Second");
}, 200);
console.log("Third");

The output of this code would be:

First
Third
Second

What should come across here is that when the code runs, it does not wait for the setTimeout to finish before executing console.log(“Third”), this is asynchronous code in action!

At first glance this seems a bit dangerous and maybe a bit confusing because it feels like you have less control of how the code executes. In reality though, this allows JavaScript to operate without having to worry about ‘Blocking Functions’.

A Blocking Function is code that will stop the execution of a program until it finishes (also called a synchronous call). This means that if you were performing an AJAX request that was receiving a large amount of data, the request would idle the rest of the program until it had completed, possibly slowing load times. If the call were asynchronous however, the server could continue executing the rest of the program while the AJAX request loaded.

This may have occurred to you while reading the preceding paragraphs, but what if you needed the data back from that AJAX request before you could continue executing the rest of the program? You’d essentially be stuck because your code would fail when it tries to access the data that doesn’t exist yet.

This is exactly where promises come in handy! A promise is a way of asking the code to let you know when an asynchronous process has been completed and then run a different block of code, while still allowing the rest of an application to run.

That’s it for part one which has set the scene for promises and hopefully given you an understanding of asynchronous code and how we can use it. In the next part, I’ll begin looking at callbacks vs promises, ES6 promises and the various JS promise libraries we have at our disposal.

Promises: