Know ES6 Better!

I have been working around with ES6 for long time now and I would like to share some interesting things that I found useful in my day to day work life. You will find lots of resources describing new features, but are you really willing to accept all the syntax! May be not. So, let me get straight to my take -

1. Arguments

Consider a simple case of writing a program to add all the numbers provided as argument. Here were your options prior to ES6 -

function getSum() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}

// Functional JS Approach
function getSum() {
    return [].reduce.call(arguments, function(a,b){return a+b;});
}

ES6 introduces a concept which I remember was taught to me in C++ class and that is variadic arguments. Now we have arguments directly as array, Lets see the code -

const getSum = (...args) => {
    return args.reduce((a, b) => a + b);
}
2. Destructuring

This thing has saved lots of time while coding. When you are dealing with objects or arrays with multiple properties or with multiple arguments or even if you are not sure about the arguments ordering, Destructuring will help you. Lets see what you can do with it -

var obj = {foo: 1, foo2: 2}
var { foo, foo2 } = obj;
console.log(foo); // Logs 1

// With Array
var arr = ['tony','greg'];
var [ fname, lname ] = arr;
console.log(fname);

So basically when you have large name objects and you want to destructure the properties, you can use this simple declaration. I feel in a way its pretty much similar to macros in c++ (highly debatable though). Following is a more deep example -

function calBMI({
    weight,
    height,
    max = 25,
    callback
}) {
    var bmi = weight / Math.pow(height, 2);
    if (bmi > max) {
        console.log("You are OverWeight");
    } else console.log(bmi);
    if (callback) {
        callback(bmi);
    }
}

callBMI({
    weight,
    height
});
callBMI({
    weight,
    height,
    max: 30
});
callBMI({
    weight,
    height,
    max: 30,
    callback: function(x) {
        Do Something
    }
});

With this, you do not have to worry about argument ordering or missing arguments. Very very useful concept.

3. Default Function Parameters

This was probably much awaited concept. Previously we had to write if statements to check if the value was passed or not to give it a default value. Now we can do following -

let retFullName = (firstName, lastName = 'Cozy') =>
    return firstName + ' ' + lastName;
retFullName('Tony') // Tony Cozy
4. MAP (Data Structure)

JavaScript never had an explicit Map data structure but it had associative arrays that did the job very well. The Map object is a simple key/value collection. Any value (both objects and primitive values) may be used as either a key or a value. This data structure actually helps because it can take an iterable as a parameter which allows to create your own behavior of iteration.

Note - Internally this is different from conventional maps. Normal iteration will lead to getting elements in insertion order.

const myMap = new Map();
const obj = {'a':'b', 'c':'d'};
myMap.set("name","tony");
myMap.set("marks",[50,20,30]);
myMap.set(obj, "some value");
for (let [key, value] of myMap) {
  console.log(key + " = " + value);
}

// Output
name = tony
marks = 50,20,30
[object Object] = some value
5. SET (Data Structure)

Similar to map, sets are also available in es6. Recall, set data structure keeps only unique values and discards any duplicate values. Lets simply see an example -

const set = new Set();
set.add('a');
set.add('b');
set.add('a');

// Lets check the result
set.forEach((a) => console.log(a));
a
b

set.add({'a': 'b'});
set.add({'a': 'b'});
set.forEach((a) => console.log(a));

// Important to note this
a
b
Object { a: "b" }
Object { a: "b" }

As we see above, sets basically can take any type and will store unique values. However, in case of objects, even though I added two objects with same properties, sets treated them as unique objects because that is the JavaScript treats objects, it is unique for every instance.

6. Custom Iterators

Collections like map, set etc or even objects can have custom iterators as said above. Of-course you have the default iterators which simply iterates based on position or insertion order, there are cases when we want to iterate in defined order. You might want to know about Symbol.iterator, here is a link for detailed info - link
Lets create a map, put random values and then define an iterator to display sorted values.

const mp = new Map();
mp.set(10, 20);
mp.set(0, 12);
mp.set(3, "name");

// Custom Iterator
mp[Symbol.iterator] = function() {
    let _this = this;
    let keys = null;
    let index = 0;

    return {
        next: function() {
            if (keys === null) {
                keys = [];
                for (let key of _this.keys()) {
                    keys.push(key);
                }
                keys.sort((a, b) => a - b);
            }

            return {
                value: _this.get(keys[index]),
                key: keys[index],
                done: index++ >= keys.length
            };
        }
    }
}

let it = mp[Symbol.iterator]();
let res = it.next();
while (!res.done) {
    console.log(res.key + " = " + res.value);
    res = it.next();
}

// Output
0 = 12
3 = name
10 = 20

As always, please Email to provide your comments.