Get started with Next-Gen JavaScript

Get started with Next-Gen JavaScript

·

9 min read

Let's Jump right into it

Quick list of contents

  • let & const
  • ES6 Arrow Functions
  • Exporting & Importing modules
  • Classes
  • Spread & Rest Operator
  • Destructuring

let & const

let and const basically replace var. You use let instead of var and const instead of var if you plan on never re-assigning this "variable" (effectively turning it into a constant therefore).

Remember: const and let are scoped by code blocks while var is scoped only by function and modules.

If you want to know more about scoping read this article

ES6 Arrow Functions

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

Arrow function syntax may look strange but it's actually simple.


function printName(name) { 
    console.log(name);
}

which you could also write as:

const printName = function(name) { 
    console.log(name);
}

becomes:

const printName = (name) => { 
    console.log(name);
}

Additional tips and tricks

If you don't use arguments you have to use empty parentheses in the function declaration

const printName = () => { 
    console.log('Neven');
}

If you have exactly one argument you may omit the parentheses

const printName = name => { 
    console.log(name);
}

and last but not least if you are only returning a value you can shorten your code like this

const printName = name => name

That's equal to:

const printName = name => {
  return name;
}

Exporting & Importing modules

Usually in all modern JavaScript project you split your code across multiple JavaScript files or so-called modules. You do this to keep each file / module focused and manageable

To use this you need to utilize export and import statements

There are two different types of exports: default (unnamed) and named exports

default --> export default ...;

named --> export const someData = ...;

You can import default exports like this

import someNameYouPick from './path/to/file';

"someNameYouPick" is totally up to you, use whatever you see fit

Named exports must be imported by their name:

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

Single file can only have one default and an unlimited amount of named exports.

When importing named exports you can also import all named exports at once with this syntax

import * as someNameYouPick from './path/to/file';

This exports all variables/functions bundled into one JavaScript object. If we reference previous example to get someData you would access it like this

someNameYouPick.someData

Classes

Classes are a feature which basically replace constructor functions and prototypes. You can define blueprints for JavaScript objects with them.

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

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

In the sample above, not only the class but also a property of that class (=> name ) is defined. The syntax you see there, 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 = 'Neven';
}

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

You can also define methods in two ways, like this

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

const user = new User();
user.printMyName();

or like this (arrow function)

class User{
    name = 'Neven';
    printMyName = () => {
        console.log(this.name);
    }
}

const user = new User();
user.printMyName();

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

Another thing that comes with classes is inheritance


class Platform{
    blog = 'hashnode';
}

class Bloger extends Platform{
    name = 'Neven';
    printMyName = () => {
        console.log(this.name);
    }
}

const bloger = new Bloger();
bloger.printMyName();
console.log(bloger.blog); // prints 'hashnode'

Spread & Rest Operator

The spread and rest operators actually use the same syntax: ...

Yeah just three dots, depending on where you use it those dots become 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:

const numbers = [1, 2, 3];
const moreNumbers = [...numbers , 4, 5]; //  [1, 2, 3, 4, 5];

Same thing but on object

const data = {
    name: 'Neven'
};
const moreData = {
    ...data,
    age: 26
};

console.log(moreData)
/*
{
  name: "Neven",
  age: 26
}

*/

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

Destructuring

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

Sample for an array


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

Same thing but for an object


const userData= {
    name: 'Neven',
    age: 26
}
const {name} = userData;
console.log(name); // prints 'Neven'
console.log(age); // prints undefined
console.log(userData); // prints {name: 'Neven', age: 26}

Destructuring also comes in handy when working with functions


const printName = (userObj) => {
    console.log(userObj.name);
}
printName({name: 'Neven', age: 26}); // prints 'Neven'

Here, we only want to print the name in the function but we pass a complete person object to the function. Of course this is no issue but it forces us to call personObj.name inside of our function. We can condense this code with destructuring:

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

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 then can use in the function body.