Introduction
Explaining the whole world of ES6 in one article is impossible or impractical, therefore, this fundamentals of ES6 article is going to be a compilation of many articles. I am going to post a new article every week. So stay tuned. Every feature is going to be explained by comparing what we used to do before ES6 and what is now standard in ES6. With this technique, it will be easy for you to change your old programming habits or you can choose whichever best fits for you.
Before moving to the tutorial, let me tell you that up to this day ES6 is still in heavy development and only modern browsers support the features. But you can always use Transpilers or polyfills to get away with it. I am going to post an article on that too in the future. Enough chatting, lets start.
This is part one of my ES6 Fundamentals training series.
Contents
- let Keyword
- const keyword
- Destructuring
- Default Parameters
- Rest Parameter
Let Keyword
Let is simply a replacement for a var keyword in javascript. Var had a few problems which are now solved by let. So as per Douglas Crockford (those who don't know him, he is the "Brad Pitt" of the Javascript Community:P. He is badass) "Stop using var and start using let."
Why?
A var has function scope (it declares a variable that's visible throughout the function) even though it looks like it has block scope, whereas let is scoped to current block. Look at the example
Var: Traditional way
- var someMethod = function()
- {
- var num = 10;
- if (true)
- {
- var num = 20;
- }
- console.log(num);
- }
- someMethod();
Output
20
In the above code what I created is a variable number with value 10 in a function. Now I created a new variable number in if block-scope in a function but, even though both are in different blocks javascript doesn't care, it changed the outer number from 10 to 20.
Now let us see let (no pun intended)
Let: ES6 Way
- let someMethod = function()
- {
- let num = 10;
- if (true)
- {
- let num = 30;
- }
- console.log(num);
- }
- someMethod();
Upon executing the above code, we get,
Output
10
Therefore let uses block scope, not function scope variable.
Const keyword
If you have ever coded in java,c,c++,c# you should know the meaning of const.
Const is a type of variable whose value can never be changed. In simple terms, whatever value you assigned to a const variable, it will remain the same throughout the program. If you try to be overly smart and change the value, javascript will return an error. Before ES6 we never had const keyword as ES standards, so no comparison of old syntax with new.
Example
- const num = 20;
- if (true)
- {
- num = 10;
- }
The above program will produce an error: num is read-only, which means that you cannot change the value of const. Like, let, const also has block-level scope, so, const specified in the outer block will be totally different from variable in the inner block.
- const num = 20;
- if (true)
- {
- let num = 10;
- console.log(num);
- }
- console.log(num);
Output
1020
In the above program, we created a const variable num in outer scope but in an inner scope, we re-defined a new variable with the same name num with value 10. So console.log in inner scope will return 10 and the outer scope log will return 20.
Destructuring assignment
Let's talk about this new cool feature of ES6. If you have ever coded in Python then you must be familiar with the word. For others, destructuring means extracting data from array or objects into variables. This might sound little odd at first, but once you understand how it works you'll want to use it everywhere in your code.
Ok so let's see an example.
- let num1 = 10;
- let num2 = 20;
- let arr = [num2,num1];
- [num1,num2] = arr;
-
- console.log(num1 +" "+num2);
Output
20 10
In the above code, I created two variables num1 and num2 with value 10 and 20. On line 3 I created an array whose first value is num2 (20) and second value is num1 (10). On line 4 I am not creating a new array, instead I am assiging value of num2 into num1 and value of num1 into num2. What is happening behind the scene and what we used to do before ES6 was,
- var num1 = 10;
- var num2 = 20;
- var arr = [num2, num1];
- num1 = arr[0];
- num2 = arr[1];
-
- console.log(num1 + " " + num2);
Instead of specifying each and every variable with its corresponding array index, we simply use destructuring syntax of Javascript to assign the values of array into variables.
We can further refactor our code,
- let [num1,num2] = [20,10];
So we can declare and initialize our variable in a simple line.
Right now we are destructuring an array so we are using [] brackets in declaration but in future when we are going to destructure objects we will use {} instead of [] like let {a, b}. We will talk about that later. But right now focus on array destructuring.
We can also assign a function which returns an array like this,
- let returnArray = function()
- {
- return [20, 10];
- }
-
- let [num1, num2] = returnArray();
It will produce the same result.
Now let's say instead of returning an array with size 2 we are returning with a size of 4 elements. What will happen in that case?
- let returnArray = function()
- {
- return [20, 10, 30, 40];
- }
- let [num1, num2] = returnArray();
- console.log(num1, num2);
Output- when logging out num1 and num2 will be,
num1: 20, num2: 10
Now let's look at the next example,
- let returnArray = function()
- {
- return [20, 10];
- }
- let [num1, num2, num3] = returnArray();
What will be the output of num3 in above code?
It turns out that when we do not return an array with the required amount of size, as in this code we are returning 2 values instead of 3 for each variable, the variable without a value will be #ff0000.
This was cool and all but where destructuring really shines in when we are using objects. When we want to initialize a variable from an object's property we can use the power of destructuring.
First, let's see an old way of doing it.
- var Person =
- {
- fname: "Sanyam",
- lname: "Singh",
- age: "200"
- };
-
- var firstName = Person.fname;
- var lastName = Person.lname;
- var userage = Person.age;
In the above code, Person object has 3 properties fname, lname, and age. We created 3 variables firstName, lastName, userage and initialized with the values of Person object properties.
Now let's see the new way of doing it using destructuring.
- let Person =
- {
- fname: "Sanyam",
- lname: "Singh",
- age: "200"
- };
- let
- {
- fname: firstName,
- lname: lastName,
- age: userage
- } = Person;
We'd get the same output as above but in this case we used the power of destructure.
Remember that now we are using {} instead of [] on line 6. One more thing to remember - let {fname: firstName, lname: lastName, age: userage} the left side is the name of the property and the right side is the name of the new variable, so fname is the name of property and firstName is name of our new variable declared.
We can refactor our code a bit more,
- let Person =
- {
- fname: "Sanyam",
- lname: "Singh",
- age: "200"
- };
- let
- {
- fname,
- lname,
- age
- } = Person;
The above code will create 3 new variables with same name of that of property. fname, lname, age
You can now console log your fname, lname, and age like so - console.log(fname) and you'll get Sanyam as result. Now you know the basics of destructuring. We can move on to the next topic. If you want some more examples of destructuring with complex objects. Comment below and I'll provide some more examples.
Default Parameter
Default parameters for me is one of the biggest features of ES6. Seriously, little features like these create a big impact in day to day coding. Default parameters allow function parameters to be initialized with default values if no value or #ff0000 is passed. Then what about statement means that if you do pass any value to the function argument, your function will assign a default value.
First let's see how we used to do it the old way,
- var someMethod = function someMethod(num1, num2)
- {
- num1 = (num1 === #ff0000) ? 10 : num1;
- num2 = (num2 === undefined) ? 20 : num2;
- console.log(num1 + " " + num2);
- };
- someMethod();
In the above code, someMethod function contains 2 parameters num1, num2. In the definition of the function we are checking if num1 or num2 is undefined then use 10 and 20 respectively as default values otherwise use the value passed into num1 and num2 variable. The conditional operator (? : ) is just shorthand of if-else.
Now let's see the ES6 Way,
- var someMethod = function(num1 = 10, num2 = 20)
- {
- console.log(num1 + " " + num2);
- };
- someMethod();
See how simple it is? We just passed default values in function parameter using = operator. So the output will be 10 and 20.
Rest Parameter
The rest parameter syntax allows us to represent an indefinite number of arguments as an array. In simple terms when you don't know how many parameters a function is going to get, we should use rest. Rest helps to create an array of all the arguments that were passed to the function. Syntax to use a rest parameter is simple.
- let someMethod = function(...restParam){}
- someMethod(1,2,3,4,5,6);
In the above program, I sent 6 parameters that will now be added to restParam array. Rest is different from the arguments object which we used to do before ES6. Arguments object is different from rest parameter in a way that rest is a true array, that means all the operations which we can do on any normal array, can be performed on rest array too, whereas arguments array was not the true form of an array.
Now let's see the traditional way of doing things,
- var someMethod = function(name)
- {
- var result = 0;
- console.log("Name is: " + name);
- console.log("Sum of all other parameters are: ");
-
- for (var i = 1; i < arguments.length; i++)
- {
- result += arguments[i];
- }
- console.log(result);
- };
- someMethod("Sam", 20, 30, 40, 50, 60);
In the above program, I am using arguments object to loop over all the parameters that were passed to function. This will work, but arguments object is not a true type of array so some of the operations that an array can perform might not be available for argument array. So, use the Rest parameter.
- let someMethod = function(name, ...restParameter)
- {
- let result = 0;
- console.log("Name is: " + name);
- console.log("Sum of all other parameters are: ");
- restParameter.forEach(function(n)
- {
- result += n;
- });
- console.log(n);
- }
- someMethod("Sam", 20, 30, 40, 50, 60);
This will generate the same result, but this time instead of using arguments, I am using rest parameter which now contains forEach feature as it is a true array whereas argument object does not contain any forEach feature.
Summary
So that's all folks for today. Hit me in comments with suggestions or questions.