A sort of a reminder I put together for myself, this time it’s some of the ES6 additions to javascript.

Links

http://es6-features.org

Rest parameter with function parameters

With the rest parameter we can create functions that take a variable number of arguments. These arguments are stored in an array that can be accessed later from inside the function.

function howMany(...args) {
 return args.length;
}

console.log("Arguments passed: " + howMany(0,1,2));
// Outputs "Arguments passed: 3"
console.log("Arguments passed: " + howMany("User", null, [1,2,3], {name: "Peter"}));
// Outputs "Arguments passed: 4"

The rest parameter eliminates the need to check the args array and allows us to apply map(), filter() and reduce() on the parameters array.

const sum = (...args) => {
  return args.reduce((a, b) => a + b, 0);
}

console.log("Sum is: " + sum(1,2,3));
// Outputs "Sum is: 6"
console.log("Sum is: " + sum());
// Outputs "Sum is: 0"

Spread operator for unpacking arrays in-place

ES6 introduces the spread operator, which allows us to expand arrays and other expressions in places where multiple parameters or elements are expected.

const arr = [1,52,10,17];
const max = Math.max(...arr);
// max would have a value of 52

Spread operator only works in-place, such as an argument to a function or in an array literal.

// This will not work:
let arr 2 = ...arr;

// This will work:
let arr2 = [...arr];

Destructuring Assignment for Extracting Values from Objects

Destructuring assignment is special syntax introduced in ES6, for neatly assigning values taken directly from an object.

const user = { name: 'John Doe', age: 34 };
// ES5
const name = user.name;
const age = user.
// ES6
const { name, age } = user;

Destructuring also allows you to assign a new variable name when extracting values.

const user = { name: 'John Doe', age: 34 };
const { name: userName, age: userAge } = user;
// userName is "John Doe", userAge is 34

We can also destructure values from nested objects.

const user = {
  johnDoe: { 
    age: 34,
    email: 'johnDoe@freeCodeCamp.com'
  }
};

const { johnDoe: { age: userAge, email: userEmail }} = user;

One key difference between the spread operator and array destructuring is that the spread operator unpacks all contents of an array into a comma-separated list so you cannot choose which elements you want to assign to variables. Array destructuring allows exactly that.

const [a, b] = [1, 2, 3, 4, 5, 6]; // a = 1, b = 2
const [a, b,,, c] = [1, 2, 3, 4, 5, 6]; // a = 1, b = 2, c = 5

Template literals

Template literals allow you to create multi-line strings and to use string interpolation features to create strings. Here we use backticks (`), not quotes (' or "), to wrap the string, and to add variables we use ${variable}. This saves inserting \n within strings, and we don’t have to use concatenation with the + operator anymore. We can also include other expressions in our string literal, for example ${a + b}.

const person = {
  name: "John Doe",
  age: 39
};

const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;

console.log(greeting);

// Output:
// "Hello, my name is John Doe!"
// "I am 39 years old."

Object Property Shorthand

Object literal declaration using Object property shorthand eliminate the redundancy of having to write x: x.

// ES5
const getMousePosition = (x, y) => ({
  x: x,
  y: y
});

// ES6
const getMousePosition = (x, y) => ({ x, y });

Concise Declarative Functions

With ES6, we can remove the function keyword and colon altogether when defining functions in objects.

const person = {
  name: "Taylor",
  sayHello: function() {
    return `Hello! My name is ${this.name}.`;
  }
};

// ES6
const person = {
  name: "Taylor",
  sayHello() {
    return `Hello! My name is ${this.name}.`;
  }
};

Class syntax for defining a constructor function

ES6 introduces a new syntax to create objects, using a class syntax. This is just syntax, and not a full-fledged class-based implementation of an object-oriented paradigm, unlike in languages such as Java, Python, Ruby, etc. The class syntax simply replaces the constructor function creation.

// ES5
var SpaceShuttle = function(targetPlanet){
  this.targetPlanet = targetPlanet;
}
var zeus = new SpaceShuttle('Jupiter');

// ES6
class SpaceShuttle {
  constructor(targetPlanet) {
    this.targetPlanet = targetPlanet;
  }
}
const zeus = new SpaceShuttle('Jupiter');

Getters and setters in class

Getter functions are meant to simply return (get) the value of an object’s private variable to the user without the user directly accessing the private variable.

Setter functions are meant to modify (set) the value of an object’s private variable based on the value passed into the setter function. This change could involve calculations, or even overwriting the previous value completely.

class Thermostat {
  constructor(tempFahrenheit) {
  // store temperature in Celsius
    this._temperature = 5/9 * (tempFahrenheit - 32);
  }
  get temperature() {
    return this._temperature;
  }
  set temperature(updatedTemp) {
    this._temperature = updatedTemp;
  }
}

const thermos = new Thermostat(76); // instantiated in Fahrenheit scale
let temp = thermos.temperature; // 24.44 in Celsius
thermos.temperature = 26; // set in Celsius
temp = thermos.temperature; // 26 in Celsius

Modules, importing and exporting

If we want to use a function from one javascript file in another file, now we can use the import/export commands instead of copying our code.
To use this functionality first we need to create a script in our HTML document with a type of module.

<script type="module" src="filename.js"></script>

We can export single or multiple functions at once.

// inside string_functions.js
const uppercaseString = (string) => {
  return string.toUpperCase();
}
const lowercaseString = (string) => {
  return string.toLowerCase()
}

export {uppercaseString, lowercaseString};

We can import specific functions from a file, or use import * as syntax which imports all functions and creates an object with a name of our choice.

import {uppercaseString, lowercaseString} from './string_functions.js';
// or
import * as stringFunctions from "./string_functions.js";

uppercaseString("hello");
lowercaseString("WORLD!");
// or
stringFunctions.uppercaseString("hello");

We can specify a fallback value for a module or a file by using keyword default (default can only be a function, not a let, const or var). When importing a default value we omit the {} brackets.

export default function concatenate(a, b) {
  return a + b;
}

// import
import concatenate from "./filename.js";

Promises

A promise in JavaScript is exactly what it sounds like – we use it to make a promise to do something, usually asynchronously. When the task completes, we either fulfill our promise or fail to do so. Promise is a constructor function, so we need to use the new keyword to create one. It takes a function as its argument, with two parameters – resolve and reject. These are methods used to determine the outcome of the promise.

A promise has three states: pending, fulfilled, and rejected. The resolve and reject parameters given to the promise argument are used to complete the promise. We use resolve when a success condition is met (promise fulfilled), and reject when fail condition is met (promise rejected). These are methods that take an argument, which can be anything – for example a string or an object (to return data on success).

const myPromise = new Promise((resolve, reject) => {
  if(success condition here) {
    resolve("Promise was fulfilled");
  } else {
    reject("Promise was rejected");
  }
});

Fulfilling a promise with “then” and handling with “catch”

Promises are most useful when we have a process that takes an unknown amount of time in our code (i.e. something asynchronous), often a server request. When we make a server request it takes some amount of time, and after it completes we usually want to do something with the response from the server. This can be achieved by using the then method.

The then method is executed immediately after our promise is fulfilled with resolve. It takes result as argument, which comes from the argument given to the resolve method.

We use catch method when our promise has been rejected. It is executed immediately after a promise’s reject method is called.

myPromise.then(result => {
  console.log(result);
});

myPromise.catch(error => {
  console.log(error);
});

For-Of operator

// instead of this
for (let i = 0; i < someArray.length; i++) {
  ...
}
// we can use this
for (let i of someArray) {
  ...
}

Leave a Reply

Your email address will not be published. Required fields are marked *