ES6 Features
Tags: javascript, es6, webdev, frontend
Published: 2021-05-06 15:52:41

**var:** Before ES6, variables were declared using var. var declarations are globally scoped or function/locally scoped. When var is declared outside of a function, it is said to be globally scoped. If var is declared within a function, then it is function/locally scoped.
```
 var greetings = 'hey buddy';
 function myFunc() {
    var hello = 'hello';
 }
```

Here, greetings is globally scoped, because it is declared outside of a function. And hello is locally scoped since it is declared inside a function.
var variables can be re-declared and updated within the same scope and it won't throw an error.
```
var greetings = 'hey buddy';
var greetings = 'bye buddy';
```
And we can also do like this-
```
var greetings = 'hey buddy';
greetings = 'bye buddy';
```
Another important thing is that var variables are hoisted to the top of their scope and initialized with a value of undefined. The main problem with var declaration is that it is able to redefine a variable and if you have declared the same variable in other parts of your code you will get surprising output and this will likely causer bugs in the code.

**Let:** Let is block scoped. So, what is a block? You can think of any code that is bounded by the curly {} braces. So, variable declared using let is only available inside that block. Let me give an example:
```
if (100 > 10) {
    let greeting = 'hey buddy';
    console.log(greeting); // "hey buddy"
}
console.log(greeting) // greeting is undefined
```
So, we can see that greeting is undefined outside of the block. Another important thing about let is that it can be updated but not re-declared. And let is hoisted to the top of its scope but never initialized. So, if you try to access let variable before declaration, it will throw an error.

**const:** const and let are basically the same. The main difference between these two is that, const cannot be updated or re-declared.
```
const greetings = 'hey buddy';
greetings = 'hello buddy'; //error: Assignment to constant variable
const greetings = 'hey buddy';
cosnt greetings = 'hello buddy'; //error: Identifier 'greetings' has already been declared.
```
So, every const variable has to be initialized at the the time of its declaration.
var declarations and hoisting: var declarations are treated as if they were declared at the top of the function (enclosing block) or in the global scope if they were declared outside of a function. So, in a layman's term this is called hoisting. Let me give an example:
```
function getName(condition){
    if(condition) {
        var name = 'Jalil';
        console.log(name)
    }
    else {
        console.log(name)
    }
    console.log(name)
}
```
So, if you pass true as an argument in the function you get the output from if and the enclosing block blocks, otherwise, from else and enclosing blocks. But, notice that the name is only declared in the if block. So, what is going on here! What is happening is that variable name is hoisted at the top of the function but within the scope of the function. That's why everywhere inside the function it is available.

**Binding:** Variable is another word can be said as a binding. When we declare/initialize a variable, what we actually do is binding the value to a name. Well it happens inside a scope obviously. So, what is a scope? You can think scope as a specific part of the program.
So, binding happens when actually we declare or initialize a variable using var, let or const in JavaScript.

**Block Level Declarations:** If variable is declared in a block-level scope using let or const they cannot be accessed outside of the block scope. Block scope can be created in the following places: 
 1. Within a function (function block).
 2. Within a block (bound with curly {} braces)
```
function getMoney(condition) {
    if(condition) {
       let amount = '100$';
       console.log(amount);
    }
    else {
       return null;
    }
}
```
In this function, amount is only accessible inside the if block. Because it was not hoisted at the top so the name is not accessible inside the else or enclosing blocks.

**Arrow functions:** These functions were introduce in ES6. These allow us to write shorter function syntax.
```
greeting = () {
    return 'hello world';
}
```
It gets even shorter if you it has only one statement. You need not to mention the return keyword and also don't need to put curly braces. `greeting = () => 'hello world';`

If the function has a single argument then the parentheses can also be omitted .
```
let name = 'Kudos';
greeting = name => 'hello' + name;

```
With arrow functions the 'this' keyword always represents the object that defined the arrow function.

**Spread Operator:** The spread operator '…' is used to expand an iterable or an array. For example,
```
const arrTxt = ['hello', 'Mars', 'goodbye', 'Earth'];
console.log(arrTxt); // ['hello', 'Mars', 'goodbye', 'Earth']
console.log(...arrTxt): // hello Mars goodbye Earth
```
Spread operator can be used to copy an array into another array.
```
const arr1 = ['hello', 'world'];
const arr2 = [...arr1, 'I', 'love', 'you'];
console.log(arr2) // ['hello', 'world', 'I', 'love', 'you']
```
Spread operator can also be used with object literals. For example,
```
const obj1 = {x:1, y:2};
const obj2 = {z:3};
const obj = {...obj1, ...obj2};
console.log(obj) // {x:1, y:2, z:3}
```
Default function parameters: It allows named parameter to be initialized with default values if no value or 'undefined' is passed. For example,
```
function add(a, b = 4) {
    return a + b;
}

add(5, 5) // 9
add (5) // 9
add (5, undefined) //9
```
**Hoisting:** It is a default behavior of JavaScript of moving all the declarations (not initializations) at the top of the scope before execution.
```
function hoisting() {
    a = 10;
    let b = 50;
}
hoisting();

console.log(a); // 10
console.log(b): // ReferenceError: b is not defined
```
In JavaScript, all undeclared variables are implicitly bound to global context. In other words, they are global variables. This is why when we logged the variable 'a' the output was correct although it is inside the function scope. And since the variable 'b' is block scoped we got a 'ReferenceError'.

hoisting of var - let's see an example,

```
console.log(name);
var name = 'Katherine Langford'; //undefined
```
But, we should have got a ReferenceError instead of undefined because, we tried to access the name before declaring it.
But actually the interpreter sees it like this:

```
var name;
console.log(name); // undefined
name = 'Katherine Langford' 
```
If we would have used let instead of var it would show us ReferenceError instead. This happens because in ES6 we can't just have undeclared variables.
const behaves the same way as let when it comes to hoisting.