ECMAScript 6 – The features that are worth remembering

ECMAScript 6 – The features that are worth remembering

Javascript 6 (or by the official name ECMAScript2015) has brought a handful of features that are worth looking into. Most of them provide more elegant and intuitive ways of doing things that were possible in the old versions of Javascript.

Even though they are far from being fully supported in the modern browsers, there are transpilers out there (Webpack, Babel) that are able to transform them into plain old Javascript. Especially if you are working on a large project with a modern framework (like React or Angular), it’s very likely to encounter them.

Fat arrow functions
Spread operator
Default Parameters
Constants
Import
Classes
Maps
Sets


Fat arrow functions

The main advantage of a fat arrow function is that it has shorter syntax than a function expression.

Syntax

(param1, param2, …, paramN) => {statements} 
single_param => {statements} 
() => {statements}
(param2, param2, …, paramN) => return_expression

is equivalent to

(param2, param2, …, paramN) => {return return_expression}

The () are optional for a single argument, but mandatory for no arguments – ex map(item => item.value) 

Destructuring assignment within the parameter list is also supported. Example:

var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

No binding for this

The most important thing to consider when using an arrow function is that it doesn’t create it’s own this context – this has the original meaning from the enclosed context. In other words, whatever is the value of this outside the function, it will be the same inside it.

Even in ‘strict mode’ if this is global, it won’t be undefined inside arrow function. This is the only strict mode rule skipped specially for arrow functions.

 


Spread operator

Spread operator simplifies the process of iterating the elements of a list and adding them one by one in a function call as parameters or on array literal.

Example: 
a = [1, 2, 3];
b = [...a, 3, 4]; // [1, 2, 3, 4]
f = someFun(...a);  // f is called with arguments (1, 2, 3)

An elegant replacement for apply()

It is a common strategy already to use  Function.prototype.apply for passing elements of a list as arguments

f = someFun.apply(null, a)

turns into a more beautiful

f = someFun(...a)

An alternative to concatenate arrays

Array.concat is often used to concatenate an array to the end of an existing array. Without spread syntax this is done as:

var list1 = [1, 2, 3];
var list2 = [3, 4, 5];
list1 = list1.concat(list2); // 1, 2, 3, 3, 4, 5

With the spread operator, the concatenation looks like this:

var list1 = [1, 2, 3];
var list2 = [3, 4, 5];
list1 = [...list1, ...list2]; // 1, 2, 3, 3, 4, 5

 


Default Parameters

Before default parameters took the scene, in Javascript the default was undefined. The common strategy was to check in the body of the function if the value is undefined and provide a default value in that case.

With default parameters, these lines of code can be shrink into one line of code. Let’s see an example:

function sum(a, b) {
    if (typeof a == "undefined") {
        a = 0;
    }
    if (typeof b == "undefined")  {
        b = 0; 
    }
    return a + b;
}

Transforms into:

function sum(a = 0, b = 0) {
    return a + b;
}

 


Constants

One of the known weaknesses of Javascript is the lack of formal constants. To rectify this, the keyword const was added.

const  let’s you defined a variable whose value cannot be changed once initialized.

Beside that, the constant behave exactly like any other variable. It belongs to the scope it was declared and you can’t have another variable or constant with the same name in the same scope. If you try to change the value of a constant, Js engine will throw a type error.

Notice: this only makes the variable itself immutable, not its assigned content (for instance, in case the content is an object, this means the object itself can still be altered).

Let’s look at an example:

const Foo = {bar: 1}

Foo = {bar: 22}; // this will throw an error

Foo.bar = 2;  // this will work!!!

 


The import statement

The import statement is used to import functions, objects, or primitives which are defined in and an external module or script.  It works with a complementary export statement which defines what variables or functions are accessible from outside of that module.

Import the entire content

import * as otherModule from 'path_to_module/otherModule.js'

For example, if we want to use the function foo() from the other module, we would type otherModule.foo() (assuming, of course, that in the otherModule.js the function exist and was exported).

Import members of other module

import {memberWithLongName as member1,  member2} from 'path_to_module/otherModule.js'

We can provide aliases for members if we want to use them with a different name.

Note: this feature is not fully supported even in modern browsers yet. However, most transpilers (Bable, Webpack) are using it so if you are working with a modern framework, you will use imports.

 


Classes

Classes in Javascript are no more than syntactic sugar. They mask the prototype inheritance with a syntax that resemble Java and other mainstream languages.

class Shape { 
    constructor (idx y) 
    { 
        this.id = id; 
        this.move(x, y); 
    } 
    move (x, y) 
    { 
       this.x = x; 
       this.y = y; 
    } 
}

is equivalent to:

var Shape = function (id, x, y) { 
    this.id = id; 
    this.move(x, y); 
}; 
Shape.prototype.move = function (x, y) { 
    this.x = x; 
    this.y = y; 
};

I discussed in depth the prototype inheritance in this article: Class-based vs. Prototype-based languages.

 


Maps in Javascript

  • Map object – a simple key/value dictionary that can iterate its elements in order of insertion
  • basic operations:
    • .set(key, value) – adds a new key/value pair
    • .has(key) – checks if a key exists
    • .delete(key) – deletes an existing key (or does nothing if the key doesn’t exist
    • .size – returns the size of the map (getter only – can’t be modified)
    • clear() – clears the map

Example (check working example JS Bin on jsbin.comhttp://static.jsbin.com/js/embed.min.js?4.0.4)

var sayings = newMap();
sayings.set('dog','woof');
sayings.set('cat','meow');
sayings.set('elephant','toot');
sayings.size; // 3
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false
for(var[key, value] of sayings){
  console.log(key+' goes '+value);
}
// "cat goes meow"
// "elephant goes toot"
sayings.clear();
sayings.size; // 0

Maps – Usage

  • map object is choose over a simple object when:
    • the iteration over key-value pairs is required
    • the keys and values have the same type
    • there is no logic that operates on individual elements
  • other advantages over a simple object:
    • you can get the size of a map easily
    • an object has a prototype, therefore few keys are default (unless you specify obj = Object.create(null))
    • keys can be of any type – array keys are all string (or converted to string)

WeakMap

  • collection of key/value pairs in which the keys are objects only
  • the objects reference in the key are held weakly – they are target of GC
  • usage: – store private data for an object or to hide implementation details (check this cool blog post for more)

 


Sets in Javascript

  • collection of values
  • iterate elements in insertion order
  • a value in set may only occur once – it’s unique in the Set’s collection
  • operations:
    • .add(value) 
    • .has(value).
    • delete(value)
    • .size 

Example:

var mySet=newSet();
mySet.add(1);
mySet.add('some text');
mySet.add('foo');
mySet.has(1); // true
mySet.delete('foo');
mySet.size; // 2

for(let item of mySet)console.log(item);
//  1
//  "some text"

Converting between Array and Set

Array.from(mySet);
[...mySet2];
mySet2 = new Set([1, 2, 3, 4]);

Sets – Usage

  • when converting a set to array, the duplicate elements will be removed
  • set over array advantages:
    • checking if an element exists in a collection using indexOf for arrays is slow
    • with set you can delete elements by their value – with array you have to specify the index
    • the value NaN cannot be found with IndexOf in array
    • unique values – don’t need to keep track of the duplicates

WeakSets

  •  collection of objects
  •  an object in weakSet may only occur once
  •  usage: DOM elements – because it will not leak memory

Note: This is part of Javascript learning roadmap.

You can find the full list of features here.

Thank you for your time!

Please subscribe for more weekly web wisdom!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s