Commonly used ES6 Features
Throughout the rest of this book, a number of ES6 features will be used consistently. If you do not have prior experience with ES6 features, this brief introduction will come in handy. If you’re comfortable with ES6 features, skip this section and head to chapter 2 to get started writing your first component.
let and const
let
and const
are two new keywords that were introduced in ES6 for declaring variables. When used to declare variables, they are scoped to the block and not the function; this means they are only available within that block. Variables declared with let
can be re-assigned but cannot be redeclared within the same scope whereas those declared by const
must be assigned an initial value but cannot be redeclared within the same scope.
In summary, use let
when you plan on re-assigning new values to the variable and const
if you’re not planning to re-assign a variable. See an example of using let
let name = 'Edmond';
name = 'Atto';
console.log(name);
//output
Atto
The spread operator
The spread operator denoted by … is used to expand iterable objects into multiple elements as shown in the example below.
const cities = ["Kampala", "Nairobi", "Lagos"];
console.log(...cities);
//output
Kampala Nairobi Lagos
The spread operator can also be used to combine multiple arrays into one array containing all array elements as shown below.
const east = ["Uganda", "Kenya", "Tanzania"];
const west = ["Nigeria", "Cameroon", "Ghana"];
const countries = [...east, ...west];
console.log(countries);
//output
[ 'Uganda', 'Kenya', 'Tanzania', 'Nigeria', 'Cameroon', 'Ghana' ]
Template literals
Before ES6, strings were concatenated using the +
operator as shown in the example below.
const student = {
name: 'John Kagga',
city: 'Kampala'
};
let message = 'Hello ' + student.name + ' from ' + student.city;
console.log(message);
//output
Hello John Kagga from Kampala
ES6 introduced template literals which are essentially string literals that include embedded expressions. They are denoted by backticks instead of single or double quotes. The template literals can contain placeholders which are represented by ${expression}
. The quotes and +
operator are dropped when using template literals as shown in the rewrite of the above example below.
let message = `Hello ${student.name} from ${student.city}`;
//output
Hello John Kagga from Kampala
Default function parameters
ES6 introduced a way of adding default values to the function’s parameter list as shown below.
function greet(name = 'Fellow', greeting = 'Welcome') {
return `${greeting} ${name}`;
}
console.log(greet()); // Welcome Fellow
console.log(greet('Kagga')); // Welcome Kagga
console.log(greet('Mike', 'Hi')); // Hi Mike
A default parameter is created when an equal ( = ) is added and whatever the parameter should default to if an argument is not provided (this parameter) can be any JavaScript data type.
Destructuring
In ES6, data can be extracted from arrays and objects into distinct variables using destructuring. Here are a couple of examples
- Extracting data from an array
=> Before ES6
const points = [20, 30, 40];
const x = points[0];
const y = points[1];
const z = points[2];
console.log(x, y, z);//output
20 30 40
=> With ES6
The above example can be changed to use destructuring in ES6 as shown below.
const points = [20, 30, 40];
const [x, y, z] = points;
console.log(x, y, z);//output
20 30 40
The [ ]
represent the array being destructured and x, y, z
represent the variables where the values from the array are to be stored. You do not have to specify the array indexes because they are automatically implied. During destructing some values can be ignored for example the y
value can be ignored as shown below.
const [x, , z] = points
2. Extracting data from an object
=> Before ES6
const car = {
type: 'Toyota',
color: 'Silver',
model: 2007
};
const type = car.type;
const color = car.color;
const model = car.model;
console.log(type, color, model);//output
Toyota Silver 2007
=> With ES6
const car = {
type: 'Toyota',
color: 'Silver',
model: 2007
};
const {type, color, model} = car;
console.log(type, color, model);//output
Toyota Silver 2007
The { }
represent the object to be destructed and type, color, model
represent the variables where to store the properties from the object. There is no need of specifying the property from where to extract the value from because car
already contains a property called type
and the value is automatically stored in the type
variable.
As with array destructuring, object destructing enables extraction of only the values needed at a given time. The example below shows the extraction of only the color
property from the car object.
const {color} = car;
console.log(color);//output
Silver
Object literal Shorthand
ES6 provides a new way of initialising objects without code repetition, making them concise and easy to read. Prior to ES6, objects were initialised using the same property names as the variable names assigned to them as shown below:
let type = 'Toyota';
let color = 'Silver';
let model = 2007;
const car = {
type: type,
color: color,
model: model
};
console.log(car);
//output
{ type: 'Toyota', color: 'Silver', model: 2007 }
Looking closely at the above example, it is clear that type:type, color:color
and model:model
seem redundant. The good news is that you can remove those duplicate variable names from object properties if the properties have the same name as the variables being assigned to them as shown below.
let type = 'Toyota';
let color = 'Silver';
let model = 2007;
const car = {
type,
color,
model
};
console.log(car);//output
{ type: 'Toyota', color: 'Silver', model: 2007 }
Arrow functions
ES6 introduced a new kind of functions called arrow functions which are very similar to regular functions in behaviour but different syntactically.
As an example, follow the steps below to convert the given regular function into an arrow function.
function (name) {
return name.toUpperCase();
}
- remove the function keyword
- remove the parentheses
- remove the opening and closing curly braces
- remove the return keyword
- remove the semicolon
- add an arrow ( => ) between the parameter list and the function body
The result
name => name.toUpperCase();
Using arrow functions
As opposed to regular expressions which can either be function declarations or function expressions, arrow functions are always expressions which can only be used where expressions are valid. Arrow functions can be stored in a variable, passed as an argument to a function or stored in an object’s property.
Parentheses and arrow function parameters
If an arrow function parameter list has one element, there is no need for wrapping that element in parentheses.
name => `Hello ${name}!`
But, if there are two or more items in the parameter list or zero items, the list has to be wrapped in parentheses as shown below.
const hello = () => console.log('Hello React!'); //zero parameters
hello();
const location = (name, city) => console.log(`${name} is from ${city}.`);//two parameterslocation('John', 'kampala');
Block body syntax
When there is need to have more than one line of code in the arrow function body, the block body syntax has to be used. With the block body syntax, curly braces have to be used to wrap the function body and a return
statement has to be used to actually return something from the function as shown below.
name => {
name = name.toUpperCase();
return `${name.length} characters make up ${name}'s name`;
};
Benefits of using arrow functions
Arrow functions may be preferred because of the following:-
=> short syntax
=> they are easy to write and read
=> they automatically return when their body is a single line of code.
Classes
ES6 introduced classes that are simply a mirage that hides the fact that prototypal inheritance goes on under the hood. These classes are unlike those in class-based languages like Java. Below is an example of an ES6 class.
class Animal {
constructor(numLegs) {
this.numLegs = numLegs;
this.mammal = false;
}
isMammal() {
this.mammal = true;
}
}
When a new object is constructed from the Animal
class, the constructor will run and the variables inside it will be initialised.
Benefits of using classes
With the new class syntax, less code is required to create a function. The function contains a clearly specified constructor function and all the code needed for the class is contained in its declaration.
ES6 also introduced two new keywords, super
and extends
which are used to extend classes.
Note that classes in javascript are still functions and their behavior is not the same as those in object-oriented programming languages such as Java.