Aditya Sharma
Aditya's Blog

Aditya's Blog

Next-Gen JavaScript - Level Up

Next-Gen JavaScript - Level Up

Handy JavaScript ES6/ES7 concepts for beginners

Aditya Sharma
·Sep 1, 2021·

7 min read

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

In this article, I'll provide a brief introduction to some core next-gen JavaScript concepts, of course focusing on the ones you'll use the most in your coding joruney. And I'll also include handy code snippets for better understanding just like forever!


Contents


let & const

let and const basically replace var. let is very similar to var with the difference that the let variable has a block-level scope (i.e. the enclosing { } just like variables in other languages). On the other hand, the scope of a var variable is the entire enclosing function.

Let's have a look at an example:

function varDemo() {
  var x = 1;
  {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letDemo() {
  let x = 1;
  {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

Use const instead of var if you plan on never re-assigning this "variable". It's a good practice to assign arrays and objects as a const.

const number = 2;

try {
  number = 99;
} catch (err) {
  console.log(err);
  // expected output: TypeError: invalid assignment to const `number'
}

console.log(number);
// expected output: 2

Read more about let here.
Read more about const here.


ES6 Arrow Functions

Arrow functions are an alternate way of creating functions in JavaScript. Besides a shorter syntax, they offer advantages when it comes to keeping the scope of the this keyword.

// Traditional Function
function callMe(a) {
  console.log(a);
}

// Arrow Function Break Down

// 1. The above function can be written as:
const callMe = function(a) {
  console.log(a);
}

// 2. Remove the word "function" and place arrow between the argument 
// and opening body bracket
const callMe = (a) => {
  console.log(a);
}

Important:

  • When having no arguments, you have to use empty parentheses in the function declaration:

    const callMe = () => { 
      console.log('Something!');
    }
    
  • When having exactly one argument, you may omit the parentheses:

    const callMe = name => { 
      console.log(name);
    }
    
  • When just returning a value, you can use the following shortcut:

    const returnMe = name => name;
    // That's equal to:
    const returnMe = name => { 
      return name;
    }
    

Read more about ES6 Arrow functions here.


Exports & Imports

In all modern JavaScript projects, you split your code across multiple JavaScript files - so-called modules. You do this to manage your large code base and make it understandable.

To access functionality in another file, you need export (to make it available) and import (to get access) statements.

export

You got two different types of exports: default (unnamed) and named exports:

  • default export

    const user = {
    id: 1,
    name: 'SomeName'
    }
    // Export user
    export default user
    
  • named export

    // export individual features (can export var, let,
    // const, function, class)
    export const initialize = () => { ... }
    export const BASE_URL = 'https://xyz... '
    // Or export features declared earlier like this:
    export { initialize, BASE_URL };
    

Important

A file can only contain one default and an unlimited amount of named exports. You can also mix the one default with any amount of named exports in one and the same file.

import

  • You can import default exports like this:

    import someNameOfYourChoice from './path/to/file.js';
    

    Surprisingly, someNameOfYourChoice is totally up to you.

  • Named exports have to be imported by their name:

    import { someData } from './path/to/file.js';
    

    When importing named exports, you can also import all named exports at once with the following syntax:

    import * as upToYou from './path/to/file.js';
    

    upToYou is, well, up to you and simply bundles all exported variables/functions in one JavaScript object.
    For example, if you export const someData = ..., you can access it on upToYou like this: upToYou.someData

Read more about export here.
Read more about import here.


Classes

Classes are a feature that basically replaces constructor functions and prototypes. You can define blueprints for JavaScript objects with them just like other OOP languages.

Like this:

class User {
    constructor () {
        this.name = 'SomeName';
    }
}

const user = new User();
console.log(user.name); // prints 'SomeName'

The syntax you see above is the "old" syntax for defining properties. In modern JavaScript projects, you can use the following, more convenient way of defining class properties:

class User {
    name = 'SomeName';
}

const user = new User();
console.log(user.name); // prints 'SomeName'

You can also define methods. Either like this:

class User {
    name = 'SomeName';
    printName () {
        console.log(this.name); // this is required to refer to the class!
    }
}

const user = new User();
user.printName(); // prints 'SomeName'

Or like this:

class User {
    name = 'SomeName';
    printName = () => {
        console.log(this.name);
    }
}

const user = new User();
user.printName(); // prints SomeName

The second approach has the same advantage as all arrow functions have: The this keyword doesn't change its reference.

You can also use inheritance when using classes:

class Human {
    gender = 'male';
}

class User extends Human {
    name = 'SomeName';
    printName = () => {
        console.log(this.name);
    }
}

const user = new User();
user.printName(); // prints 'SomeName'
console.log(user.gender); // prints 'male'

Read more about class here.


Spread & Rest Operator

The spread and rest operators actually use the same syntax: ... Yes, it's just three dots! Its usage determines whether you're using it as the spread or rest operator.

Spread Operator

The spread operator allows you to pull elements out of an array (split the array into a list of its elements) or pull the properties out of an object.

Here are two examples:

// spread operator used on array
const oldArray = [1, 2, 3];
const newArray = [...oldArray, 4, 5]; // This now is [1, 2, 3, 4, 5];

// spread operator used on an object
const oldObject = {
    name: 'SomeName'
};
const newObject = {
    ...oldObject,
    age: 23
};

// newObject  would then be
{
    name: 'SomeName',
    age: 23
}

Note

The spread operator is extremely useful for cloning arrays and objects. Since both are reference types (and not primitives), copying them safely can be tricky. With the spread operator, you have an easy way of creating a clone of the object or array.

Rest Operator

The rest operator allows a function to accept an indefinite number of arguments as an array.

Here's how you use it:

const filter = (...args) => {
  return args.filter(el => el === 1)
}

console.log(filter(1, 2, 3)) // prints [1]

Read more about spread operator here.
Read more about rest operator here.


Destructuring

Destructuring allows you to easily access the elements of arrays or objects and assign them to variables.

Here's an example for destructuring an array:

const array = [1, 2, 3];
const [a, b] = array;
console.log(a); // prints 1
console.log(b); // prints 2
console.log(array); // prints [1, 2, 3]

And here for destructuring an object:

const user = {
    name: 'SomeName',
    age: 23
}
const {name} = user;
console.log(name); // prints 'SomeName'
console.log(age); // prints undefined
console.log(user); // prints {name: 'SomeName', age: 23}

Destructuring is very useful when working with function arguments. Consider this example:

const printName = (user) => {
    console.log(user.name);
}
printName({name: 'SomeName', age: 23}); // prints 'SomeName'

The above code forces us to call user.name inside of our function. We can condense this code with destructuring:

const printName = ({name}) => {
    console.log(name);
}
printName({name: 'SomeName', age: 23}); // prints 'SomeName'

We get the same result as above but we save some code. By destructuring, we simply pull out the name property and store it in a variable/argument named name which we can then use in the function body.

Read more about Destructuring here.


That's all folks! Do let me know what you liked and what can be improved in the comments below! Also, feel free to drop me a line if you don't understand something. ✌

Thanks for reading!

 
Share this