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

Getting deeper into the console

Preface: Not all of these commands are compatible in all browsers. I strongly recommend using the latest version of Google Chrome.

One of the first things budding web developers play with in JavaScript is the browser console (the real web browser). After looking at the console, the first thing everyone writes is:

console.log("Hello world!");

console.log() is a very useful command which many people use to debug and ensure their code is running the way they expect, however the console has a lot more power through lesser known commands that can help format data and even run interactive games!

Console output commands

Aside from console.log(), it is possible to filter the output based on what information it is representing. Here’s a few other console commands to be aware of:

  • console.error()
  • console.warn()
  • console.info()
  • console.debug()

Here’s the output of these commands:

Screen Shot 2016-01-07 at 12.01.18 PM

Console.group()

If you want to group a bunch of related messages together, you can use console.group() noting that you must close the group with console.groupEnd() like so:

console.group("beginning process...");
console.log("part 1 of the process.");
console.log("part 2 of the process.");
console.log("process complete.");
console.groupEnd();

This code would output like this:

Screen Shot 2016-01-07 at 12.51.52 PM

Console.table()

Getting a little more complex now, another way to display information in a much more readable format is to use console.table() which as you might guess, displays the information in an organised table. console.table() can take multiple parameters as objects or arrays and display it in a more readable format. So this code:

console.table([[1,2,3], [4,5,6], [7,8,9]]);

would output:

Screen Shot 2016-01-07 at 2.53.50 PM

For more information on how to display different information with console.table(), follow this link.

Console.time()

It is possible to create a timer that displays the amount of time that passes between a console.time() and console.timeEnd() command. To make this work, they both need to be passed in a name which will be displayed at the end. The console will then output how much time passed between each one. For example:

console.time("timer");
setTimeout(function() {
  console.timeEnd("timer");
}, 200);

would output:

Screen Shot 2016-01-07 at 1.07.19 PM.png

If you’re wondering why the example didn’t output exactly 200ms, it’s because the .490ms is how long the operations outside of setTimeout() took to run.

String substitution:

While using console.log() (or any other console output command, it is possible to use substitution to format a variable in a certain way. The console commands recognise the following types:

  • %s = string
  • %i OR %d = integer
  • %f = floating point number
  • %o = DOM element
  • %O = Javascript object
  • %c = used to apply given CSS specified by an additional parameter

So this code:

var user = {
  name: "Michael",
  age: 27
};

console.log("%s is %d years old!", user.name, user.age);

(Take note that the substitutions must match the order in which the arguments are passed in) would output:

Screen Shot 2016-01-07 at 1.16.32 PM.png

CSS in the console

This is definitely where you can start having a lot more fun trying to do interesting things. Using the substitution method you can apply CSS effects to text by passing in a string with CSS formatting like so:

var css = "color: purple; font-size: x-large";
console.log("%cThis text is much bigger than usual...", css);

will output:

Screen Shot 2016-01-07 at 1.27.35 PM

If you would like to see a much more extreme example, go to this paste bin and copy the code into your console and run it. I’ll bet you didn’t know that was possible in the console! (This example was originally created by @mikewest)

Games!?

One last example I have for you is an interactive game that runs in the console which was originally created by @jschomay. To view and play the game follow this link.

Hopefully this article gave you some insights in to how you can use the console more creatively, if only to have a bit more fun while designing your websites. If you have any other tricks, please share them in the comments.

Finally, one person you should follow to learn more about using the console is Addy Osmani (@addyosmani), a software engineer at Google who often tweets interesting tips about web development and the console like this one.

Further Reading:

Promises – Part 3 – Using the Q library

Although promises are going to be a part of ES6 and thus a part of the language going forward, the first way I ever heard of using promises in JavaScript was the library Q (link here).

Q has been around since 2009 as a way to handle promises in JavaScript and has familiar methods to the ones outlined in the previous sections on promises. It’s quite small in size (8.5kb minified) and very powerful in terms of its ability to handle promises. It also has specific methods to handle node functions (which is very handy in my current job which uses a full node.js backend).

Here are a few of the different methods in the Q library that can be useful when dealing with different situations:

Q.all([promise1(), promise2()])

Q.all() can be used to take a group of promises and return them all as a single promise. This means that you can have multiple asynchronous operations and without chaining, write code that will run only once all the promises inside the array have been resolved. So to illustrate this further, once promise1() and promise2() have been resolved, you could immediately add:

.then(function(results) { //code })

In this case, the different values returned will be stored in an array in the .then() method (in the above example, the array is the results parameter).

Another cool trick when handling the results of the Q.all() method call instead of using.then() is by using .spread(). This method allows you to spread the different results of the promises within the array across different parameters within the follow-up function, like so:

Q.all([promise1(), promise2()])
.spread([result1, result2], function(result1, result2) { //code })

This might seem a little bit like overkill but if you think about it when you’ve got a much larger array, it can help keep your code clear and concise when dealing with the different results.

There are a huge amount of other useful features in Q that I could go over but then this post will basically mirror the documentation. I do however, want to look a little bit more at some of the cooler node-related functions available within Q.

In core node, asynchronous functions return a callback rather than a promise, take for instance the fs.readFile() method:

fs.readFile('./file.txt', function read(err, data) { //code })

With Q, you can target the readFile method and ‘denodeify’ it which creates a promise wrapper and makes it return a promise, as opposed to a callback. Denodeifying can be done like this:

var fs_readFile = Q.denodeify(fs.readFile)

Now fs_readFile can be used as a function that takes the same arguments as fs.readFile() (a filename) and it will return a promise:

var promise = fs_readFile('./file.txt')

And that promise can be used just like any other promise we’ve become used to!

promise.then(function(result, err) { //code })

.denodeify() is most useful if you’re going to be using a node function more than once so you can call it again in different places. An alternative to this method is to use .nfcall() which can be used for individual cases and turning a callback style function into one which returns a promise:

return Q.nfcall(fs.readFile, './file.txt')

Sometimes however when using .nfcall() on a method, you can run into the issue of unbinding the method from it’s original owner. Luckily, Q has the .ninvoke() method to handle this without causing the binding issues, so if we were dealing with parent.method() it would be written as:

Q.ninvoke(parent, "method", arguments)

In case you were wondering, the n in the previous functions stands for node, and nf stands for node function.

Again, there are a lot more complex situations that Q can handle in regards to promises, but this post has just listed some of the more common ones. Hopefully this has been helpful and in my next post I’m going to move away from promises and into generator functions!

Thanks for reading, if you’ve got any comments, please leave them below.

Promises:

Further Reading: