A sort of a reminder I put together for myself, this time it’s some of the ES6 additions to javascript.
Links
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) { ... }