Skip to content
Thomas David Kehoe edited this page Dec 13, 2016 · 20 revisions

ES2015, or ES6 as it was previously known, was JavaScript's biggest advance. I'll list the new features in order of their importance (to me!).

#Promises

JavaScript is used is connect Internet resources. Waiting for resources such as remote databases to respond with data is a constant issue. Synchronous code froze websites while waiting for data. Asynchronous coding is the norm now, with the parts of the code running while other parts wait for data.

In ES5 and earlier, asynchronous coding used callbacks. Callbacks are double functions, in which the second function is an argument to the first function. The first function executes and then waits for the data to return, or a user to click a button, etc., and then the second function executes. Here is an example of a callback function:


myFirstFunction(function(error, data) {
   if (error) {
      console.log(error);
   } else {
      // render docs
   };
});

What if you have five or ten things to do after the data returns or the user clicks the button? You can nest callbacks:


myFirstFunction(function(error, data) {
   if (error) {
      console.log(error);
   } else {
      // render docs (function(error, data) {
           if (error) {
              console.log(error);
              } else {
              // render docs (function(error, data) {
              // and so on...
      };
   };
});

This is called callback hell or the pyramid of death.

Promises fix this problem. A promise is a proxy for a value which may be available now, in the future, or never.

Promises always have two handlers resolve and reject.

Promises have three states: pending, fulfilled, and rejected.

Promise prototypes have two methods that are almost always used:

  • .then(onFulfilled, on Rejected) takes two arguments, typically data and error.
  • .catch(onRejected) takes one argument, typically error.

Promises have four other methods which are less commonly used:

  • all is used for aggregating the results of multiple promises into an array of values.
  • race is also used with multiple promises, but returns when one of the promises fulfills.
  • reject -- not sure how this differs from catch.
  • resolve -- not sure how this differs from then.

The basic syntax of promises is:


function myFunction() {
   // ...
};

myFunction.then(
   // ...
)
.catch(
   console.log(error);
);

#let and const

Hoisting means that JavaScript allows your code to use a variable before it's declared. This can be a problem if you use the same name for different variables. Hoisting also can give you misleading error messages. Using let instead of var eliminates hoisting and instead declares block-scoped variables, which are only accessible between the curly brackets of a function.

let should always be used in for in loops. let variables can't be redeclared. Redeclaring variables seems like bad coding. let also uses less memory. let should always be used instead of var.

const is used for constants, which are also not hoisted. Constants should always be declared with const.

let and const are super easy.

#Parameter Default Values

When you create a function with parameters, consider whether any of the parameters have defaults (other than undefined, the default of all parameters). If yes, then assign the defaults:


function myFunction(x = 1, y = 2, z = 3) {
   // ...
};

#The Spread Operator ...

The spread operator is used to manipulate arrays. It splits an iterable object into individual values, i.e., represents the elements in an array. For example,


function addNumbers(a, b) {
   return a + b;
}

let data = [1, 4];
let result = addNumbers(...data);
console.log(result) // 5

You can also use the spread operator to push elements from one array into a second array:


let array1 = [2, 3, 4];
let array2 = [1, 5];

array1.push(...array2);
array1.sort();

console.log(array1); // 1, 2, 3, 4, 5]

Or push elements from two arrays into a new, third array:


let array1 = [2, 3, 4];
let array2 = [1, 5];

let array3 = [...array1, ...array2];
array3.sort();

console.log(array3); // 1, 2, 3, 4, 5]

#The Rest Parameter ...

The rest parameter is used in a function when the number of arguments exceeds the number of parameters. The rest parameter is an array that contains the rest of the arguments.

Parameters are when the function is declared. Arguments are when a function is called. Suppose you declare a function but you don't know how many arguments will be used when the function is called. You can use the rest parameter:


function myFunction(a, b, ...args) {
   console.log(args);
}

myFunction(1, 2, 3); // [3]
myFunction(1, 2, 3, 4, 5); // [3, 4, 5]

#Destructuring Arrays and Objects

Destructuring means assigning elements of an array to variables. You just create an array of variables and set it equal to an array of elements:


let [a, b, c] = [1, 2, 3];

You can even ignore values:


let [a, , c] = [1, 2, 3];

##Using the Rest Parameter When Destructuring Arrays


let [a, ...b] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // [2, 3, 4, 5]

##Object Destructuring

There's also object destructuring syntax.

#Fat Arrow Functions

this in a traditional function refers to the context object (the object inside of which the function is a property). In fat arrow functions this refers to the enclosing scope (the global or function scope). In other words, JavaScript is usually some permutation of functions within objects and objects within functions. With fat arrows this refers to the enclosing function, as compared to traditional functions in which this refers to the enclosing object.

The parameters move to the left of the arrow, instead of to the right of function:


const pi = 3.141592653589793;

let circleArea = (r) => {
   let area = pi * r * r;
   return area;
}

console.log(circleArea(3)); // 28.274333882308138

You can eliminate the curly brackets if your body fits on one line. The value is returned without a return line:


const pi = 3.141592653589793;

let circleArea = (r) => pi * r * r;

console.log(circleArea(3)); // 28.274333882308138

The fat arrow function can't be used with new.

#Enhanced Object Literals

This a new way to define properties and methods on an object:


let x = 1, y = 2;
let object = { x, y };

#Template Strings

Backticks make multi-line strings easier, string interpolation with variables, etc.

#Number Properties

ES2015 has many new properties including binary and octal notation, tests whether an number is an integer, is finite, etc.

#Math Operations

Lots of trigonometry, arithmetic, and other functions.

#Array Properties

New ways to constructing arrays from iterable objects, finding an element or its index in an array, etc.

New types of arrays that run faster, storing only numbers of a specified size.

#Set

Sets are like arrays but with unique values, i.e., no element is repeated. Sets can store any primitive type.

#WeakSet

WeakSet is like a Set but uses memory efficiently because it stores only objects, and objects that aren't referenced are removed.

#Map

Maps are like objects but with unique valleys, i.e., if an element is entered twice it's overwritten.

#WeakMap

WeakMap is like Map but can only contain objects. Maps can contain any data type.

#Object Properties

Inheritance is improved with the proto property.

Objects can be constructed from other objects using Object.assign().

#Symbol

Symbols are unique and immutable values. They are string-like objects that can't collide with other values.

Through ES5 the keys of objects could only be strings. ES2015 allowed symbols to be keys, enabling two keys to appear to be identical but have different values (confusing?).

Eleven symbols are built-in to ES2015, including iterator, match, search, and replace.

#The Iterator Protocol

A set of rules for iterating over values in an object. Rules include next() to return the next value, done() to signal the end of the collection, and value to hold the value of the current item.

#Generators

Generators are functions that return not a single value but multiple values. Generators are functions with an asterisk: function*. Calling a generator doesn't execute the function, instead you must call the function with the next() method. It then executes the function until the yield keyword is encountered.

The yield keyword yields a value and then pauses (as opposed to next, which goes on). return() ends the generator function. throw() is for exceptions. yield* yields the values of an iterable object.

#for...of Loops

forEach iterates over arrays. for...in iterates overs the keys of an object. for...of iterates over the values of an object.

#Tail Call Optimizations

This is for recursive programming, to reduce memory usage.

#ECMAScript 5

##Strict Mode

Before any other statements put "use strict". This converts silent mistakes into errors, prohibits with, limits the scope of variables, improves eval and arguments, and makes JavaScript more secure.

##New Array Methods

New array methods included forEach() for iterating over arrays, filter(), indexOf(), map(), reduce(), and others.

##New Date Methods

New date methods included Date.now().

##JSON Support

JSON methods included JSON.parse and JSON.stringify.

##Legal Trailing Commas The last element of an array can be followed by a comma.

Clone this wiki locally