The Complete Guide To Modern Javascript
The Complete Guide To Modern Javascript
The Complete Guide To Modern Javascript
8
About Me
My name is Alberto Montalesi, I
am from Italy and I am working in
Vietnam as a Software Developer
creating enterprise software.
9
Get in touch
If you want to get in touch for any type of
collaboration or discussion you can find me on:
• DevTo at https://dev.to/albertomontalesi
• Github at https://github.com/AlbertoMontalesi
10
Contributions & Donations
Any contributions you make are of course greatly
appreciated.
License
11
Set up your environment
If you already have a code editor installed on your
computer and you already know how to use the
chrome developer tools or similar tools, then you
can skip this chapter and move on.
• Atom: https://atom.io/
12
Open your browser to any page and right click
somewhere. You will see a set of options, one of which
being inspect or inspect element. If you click it it
will open the developer tools that you can use to
look at web pages code, play around with JavaScript
or debug your application.
The first tab Elements will let you look at the code of
the page you are inspecting, the second tab Console
is where you can write your JavaScript and
experiment.
13
14
JavaScript Basics
JavaScript is a programming language created by
Brendan Eich in 1995 that enables interactive web
pages and is an essential part of web applications.
<script type="text/javascript">
[YOUR_SCRIPT_HERE] </script>
<script src="/home/script.js"></script>
15
<!-- absolute path from the root of our
project -->
<script src="/home/script.js"></script>
<!-- relative path to our current folder --
>
<script src="script.js"></script>
<!-- full url to the jquery library -->
<script src="https://cdnjs.cloudflare.com/
ajax/libs/jquery/3.3.1/core.js"></script>
Variables
We use variables to store values, which can be
anything from a username, an address or an item
from our e-commerce site, for example.
17
If both var and let can be reassigned, then why
should we use let instead of var? The answer for that
requires a bit more explanation of how JavaScript
works and it will be discussed later in the Chapter 1.
19
The rule of thumb when it comes to choosing the
name for your variable is to make them descriptive.
Avoid using acronyms, abbreviations and meaningless
names.
// BAD
let cid = 12; // what is a `cid`
// GOOD
let clientID = 12; // oh, a `client id`
// BAD
let id = 12 // what id? userID? dogID?
catID?
// GOOD
let userID = 12 // be specific
// BAD
let lastloggedin = '' // hard to read
// GOOD
let lastLoggedIn = '' // camelCase
let last_logged_in = '' // snake_case
20
Whether you choose to use camelCase and capitalize
each word of the name after the first one, or you
choose to use snake_case and put an underscore
between each word, remember to be consistent and
stick to your choice.
Data Types
JavaScript is a dynamic language, meaning that on
the contrary to a static language, you don't have to
define the type of your variables when you define
them.
21
In JavaScript, there are 7 data types: 6 primitives
and the Object.
Primitives
They are:
• string
• number
• boolean
• null
• undefined
22
number is used to represent numerical values.
In JavaScript there is no specific type for Integers.
Objects
const car = {
wheels: 4,
color: "red",
}
23
This is a simple Object that i use to store properties of
my car.
const car = {
wheels: 4,
color: "red",
drive: function(){
console.log("wroom wroom")
}
}
console.log(Object.keys(car)[0]) // wheels
console.log(typeof Object.keys(car)[0]) //
string
car.drive();
// wroom wroom
24
Create an empty Object
car.color = 'red';
console.log(car)
// {color: "red"}
const car = {
wheels: 4,
color: "red",
}
25
console.log(car.wheels);
// 4
console.log(car['color']);
// 'red'
const car = {
wheels: 4,
color: "red",
"goes fast": true
}
console.log(car.goes fast);
// syntax error
console.log(car['goes fast'])
// true
26
Let’s say that our application receives an input from a
user, which is then saved into a variable that will be
used to access our object.
const cars = {
ferrari: "california",
porsche: "911",
bugatti: "veyron",
}
// user input
const key = "ferrari"
console.log(cars.key);
// undefined
console.log(cars['key']);
// undefined
console.log(cars[key]);
// california
27
As you can see, we need to use bracket notation to
access the property of the Object via its key, stored in
our variable.
Copying Objects
let car = {
color: 'red'
}
let secondCar = car;
let car = {
color: 'red'
}
let secondCar = car;
car.wheels = 4
console.log(car);
28
// {color: 'red', wheels: 4}
console.log(secondCar);
// {color: 'red', wheels: 4}
console.log(car == secondCar);
// true
console.log(car === secondCar);
// true
29
// false
emptyObj1 === emptyObj2;
// false
const obj1 = {a: 1};
const obj2 = {a: 1};
obj1 == obj2;
// false
obj1 === obj2;
// false
const car = {
color:'red'
}
const secondCar = Object.assign({}, car)
car.wheels = 4;
console.log(car);
// {color: 'red', wheels: 4}
30
console.log(secondCar);
// {color: 'red'}
Arrays
For example:
31
const fruitBasket =
['apple','banana','orange']
const fruitBasket =
['apple','banana','orange']
console.log(fruitBasket[0])
// apple
console.log(fruitBasket[1])
// banana
console.log(fruitBasket[2])
// orange
const fruitBasket =
['apple','banana','orange'];
// get the length of the Array
console.log(fruitBasket.length);
// 3
// add a new value at the end of the array
fruitBasket.push('pear')
console.log(fruitBasket);
// ["apple", "banana", "orange", "pear"]
32
// add a new value at the beginning of the
array
fruitBasket.unshift('melon')
console.log(fruitBasket);
// ["melon", "apple", "banana", "orange",
"pear"]
// remove a value from the end of the array
fruitBasket.pop()
console.log(fruitBasket);
// ["melon", "apple", "banana", "orange"]
// remove a value from the beginning of the
array
fruitBasket.shift()
console.log(fruitBasket);
// ["apple", "banana", "orange"]
33
Determining types using typeof
typeof(null)
34
We know that null is a primitive, so should we expect
to see null as the result?
typeof(null)
// object
Functions
Functions are a very important tool we use to perform
tasks and calculations of all kinds.
In JavaScript we can declare a function in different
ways.
function greet(name){
console.log("hello " + name);
}
greet("Alberto")
// hello Alberto
35
parameter while the code inside of the curly brackets
is a statement, in this case a very simple
console.log().
36
let myCar = {
make: "bmw",
color: "red"
}
console.log(myCar)
// {make: "bmw", color: "red"}
function changeColor(car){
car.color = "blue"
}
changeColor(myCar)
console.log(myCar)
// {make: "bmw", color: "blue"}
37
greeter("Alberto")
// hello Alberto
38
We will look at arrow functions in detail in Chapter 2.
What is Scope? \
The scope of a variable controls where that variable
can be accessed from.
We can have a global scope meaning that the variable
can be accessed from anywhere in our code or we can
have a block scope meaning that the variable can be
accessed only from inside of the block where it has
been declared.
39
}
console.log(mySecondInt);
// 2
const myCar = {
color: 'red',
logColor: function(){
console.log(this.color)
}
}
myCar.logColor();
// red
function logThis(){
console.log(this);
}
41
logThis();
// Window {...}
const myCar = {
color: 'red',
logColor: function(){
console.log(this.color)
}
}
const unboundGetColor = myCar.logColor;
42
console.log(unboundGetColor())
// undefined
const boundGetColor =
unboundGetColor.bind(myCar)
console.log(boundGetColor())
// red
43
They are both similar in that both methods call a
function with a given this value. The arguments they
accept are a bit different.
function Car(make,color){
this.carMake = make;
this.carColor = color;
}
function MyCar(make,color){
Car.call(this,make,color)
this.age = 5
}
const myNewCar = new MyCar('bmw','red')
console.log(myNewCar.carMake)
// bmw
console.log(myNewCar.carColor)
// red
44
Look at this example with .apply() to see the
differences between the two.
function Car(make,color){
this.carMake = make;
this.carColor = color;
}
function MyCar(make,color){
Car.apply(this,[make,color])
this.age = 5
}
const myNewCar = new MyCar('bmw','red')
console.log(myNewCar.carMake)
// bmw
console.log(myNewCar.carColor)
// red
As you can see, the result was the same but in this
case .apply() accepts an array with a list of
arguments.
46
JavaScript Basics Quiz
JS-01 Which of the following ways of naming a
variable is wrong?
var very_important = "very_important"
var VeRY_ImP_orTant =
"VeRY_ImP_orTant"
boolean
null
Object
47
JS-04 What is the correct output of the
following code?
true
undefined
false
null
const fruitBasket =
['apple','banana','orange'];
fruitBasket.unshift('melon')
console.log(fruitBasket);
["melon"]
48
Chapter 1: Var vs Let vs Const &
the temporal dead zone
With the introduction of let and const in ES6, we
can now better define our variables depending on our
needs. During our JavaScript primer we looked at
the basic differences between these 3 keywords, now
we will go into more detail.
Var
49
console.log(functionScoped);
}
myFunc();
// I am available inside this function
console.log(functionScoped);
// ReferenceError: functionScoped is not
defined
Let
// using `let`
let x = "global";
if (x === "global") {
let x = "block-scoped";
50
console.log(x);
// expected output: block-scoped
}
console.log(x);
// expected output: global
// using `var`
var y = "global";
if (y === "global") {
var y= "block-scoped";
console.log(y);
// expected output: block-scoped
}
console.log(y);
// expected output: block-scoped
51
Const
Important:
This does not mean that variables declared with const
are immutable.
const person = {
name: 'Alberto',
age: 25,
}
person.age = 26;
52
console.log(person.age);
// 26
const person = {
name: 'Alberto',
age: 25,
}
person.age = 26;
console.log(person.age);
// 26
Object.freeze(person)
person.age = 30;
console.log(person.age);
// 26
53
The temporal dead zone
console.log(i);
var i = "I am a variable";
// expected output: undefined
console.log(j);
let j = "I am a let";
// expected output: ReferenceError: can't
access lexical declaration `j' before
initialization
The main differences lie in the fact that var can still
be accessed before they are defined. This causes the
value to be undefined. While on the other hand, let
lets the variables sit in a temporal dead zone until they
are declared. And this causes an error when accessed
before initialization, which makes it easier to debug
code rather than having an undefined as the result.
55
• Refactor let to const only after some code has to be
written, and you're reasonably sure that you've got a
case where there shouldn't be variable reassignment.
56
End of Chapter 1 Quiz
1.1 What is the correct output of the following
code?
Hello
Good morning
Farewell;
let x = 100;
if (x > 50) {
let x = 10;
}
console.log(x);
10
100
50
58
1.4 What is the correct output of the following
code?
console.log(constant);
const constant = 1;
undefined
ReferenceError
59
Chapter 2: Arrow functions
What is an arrow function?
60
var greeting = () => {
return "hello";
}
Implicitly return
61
const arrowFunction = (name) => {
return `hello ${name}`;
}
62
To tell JavaScript what's inside the curly braces is
an object literal we want to implicitly return, we need
to wrap everything inside parenthesis.
63
<div class="box open">
This is a box
</div>
.opening {
background-color:red;
}
// grab our div with class box
const box = document.querySelector(".box");
// listen for a click event
box.addEventListener("click", function() {
// toggle the class opening on the div
this.classList.toggle("opening");
setTimeout(function(){
// try to toggle again the class
this.classList.toggle("opening");
},500);
});
64
Since we know that arrow functions inherit the value
of this from the parent scope, we can re-write our
function like this:
const box =
document.querySelector(".box");
// listen for a click event
box.addEventListener("click", function() {
// toggle the class opening on the div
this.classList.toggle("opening");
setTimeout(()=>{
// try to toggle again the class
this.classList.toggle("opening");
},500);
});
65
The next two examples show when to be careful using
this inside of arrows.
Example 1
const button =
document.querySelector("btn");
button.addEventListener("click", () => {
// error: *this* refers to the `Window`
Object
this.classList.toggle("on");
})
Example 2
const person1 = {
age: 10,
grow: function() {
this.age++;
console.log(this.age);
}
}
person1.grow();
// 11
const person2 = {
age: 10,
66
grow: () => {
// error: *this* refers to the `Window`
Object
this.age++;
console.log(this.age);
}
}
person2.grow();
A quick example:
function example(){
console.log(arguments[0])
}
example(1,2,3);
// 1
67
Similarly to what we saw with the this keyword,
Arrow functions inherit the value of the arguments
object from their parent scope.
68
}
showWinner("Usain Bolt", "Justin Gatlin",
"Asafa Powell" )
// "Usain Bolt was the winner"
69
End of Chapter 2 Quiz
2.1 What is the correct syntax for an arrow
function?
const person = {
age: 10,
grow: () => {
this.age++;
},
70
}
person.grow();
console.log(person.age);
10
11
undefined
function(arg) {
console.log(arg);
}
71
Chapter 3: Default function
arguments
Prior to ES6, setting default values to function
arguments was not so easy. Let's look at an example:
function
getLocation(city,country,continent){
if(typeof country === 'undefined'){
country = 'Italy'
}
if(typeof continent === 'undefined'){
continent = 'Europe'
}
console.log(continent,country,city)
}
getLocation('Milan')
// Europe Italy Milan
getLocation('Paris','France')
// Europe France Paris
72
undefined and in that case we are giving them a
default value.
function
getLocation(continent,country,city){
if(typeof country === 'undefined'){
country = 'Italy'
}
if(typeof continent === 'undefined'){
continent = 'Europe'
}
console.log(continent,country,city)
}
getLocation(undefined, undefined,'Milan')
// Europe Italy Milan
getLocation(undefined,'Paris','France')
// Europe Paris France
73
If we want to replace any of the first arguments with
our default we need to pass them as undefined, not
really a nice looking solution. Luckily ES6 came to the
rescue with default function arguments.
74
// In this case 0.15 will be bound to the
tip
calculatePrice(100, undefined, 0.15)
function calculatePrice({
total = 0,
tax = 0.1,
tip = 0.05} = {}){
return total + (total * tax) + (total *
tip);
}
const bill = calculatePrice({ tip: 0.15,
total:150 });
// 187.5
calculatePrice({});
// 0
calculatePrice();
// 0
calculatePrice(undefined)
// 0
function calculatePrice({
total = 0,
76
tax = 0.1,
tip = 0.05}){
return total + (total * tax) + (total *
tip);
}
calculatePrice({});
// cannot read property `total` of
'undefined' or 'null'.
calculatePrice();
// cannot read property `total` of
'undefined' or 'null'.
calculatePrice(undefined)
// cannot read property `total` of
'undefined' or 'null'.
77
End of Chapter 3 Quiz
3.1 Write the code to accomplish the following
task:
function calculatePrice(total,arg1,arg2) {
return total + (total * tax) + (total *
tip);
}
calculatePrice(10);
// expected result: 11.5
var b = 3;
function multiply(a,b=2){
return a * b;
}
console.log(multiply(5));
78
5
10
15
79
Chapter 4: Template literals
Prior to ES6 they were called template strings, now we
call them template literals. Let's have a look at what
changed in the way we interpolate strings in ES6.
Interpolating strings
80
Expression interpolations
In ES5 we used to write this:
var a = 1;
var b = 10;
console.log('1 * 10 is ' + ( a * b));
// 1 * 10 is 10
var a = 1;
var b = 10;
console.log(`1 * 10 is ${a * b}`);
// 1 * 10 is 10
81
const content = `hello,
my name is Alberto
how are you?`;
Nesting templates
82
console.log(markup);
// <ul>
// <li> Alberto</li>,<li> Caroline</
li>,<li> Josh</li>
// </ul>
83
If the condition before the ? can be converted to true
then the first value is returned, else it's the value after
the : that gets returned.
84
name: "Trent Reznor",
age: 53,
song: 'Hurt'
};
// <div>
// <p> Trent Reznor is 53 years old and
wrote the song Hurt
// </p>
// </div>
const groceries = {
meat: "pork chop",
veggie: "salad",
fruit: "apple",
others: ['mushrooms', 'instant noodles',
'instant soup'],
}
// this function will map each individual
value of our groceries
85
function groceryList(others) {
return `
<p>
${others.map( other => ` <span>$
{other}</span>`).join('\n')}
</p>
`;
}
// display all our groceries in a p tag,
the last one will include all the one from
the array **others**
const markup = `
<div>
<p>${groceries.meat}</p>
<p>${groceries.veggie}</p>
<p>${groceries.fruit}</p>
<p>${groceryList(groceries.others)}</p>
<div>
`
// <div>
// <p>pork chop</p>
// <p>salad</p>
// <p>apple</p>
// <p>
86
// <p>
// <span>mushrooms</span>
// <span>instant noodles</span>
// <span>instant soup</span>
// </p>
// </p>
// <div>
87
let person = "Alberto";
let age = 25;
function
myTag(strings,personName,personAge){
let str = strings[1];
let ageStr;
personAge > 50 ? ageStr = "grandpa" :
ageStr = "youngster";
return personName + str + ageStr;
}
let sentence = myTag`${person} is a ${age}
`;
console.log(sentence);
// Alberto is a youngster
89
End of Chapter 4 Quiz
4.1 Write the code to accomplish the following
task:
let a = "Hello,";
let b = "is";
let c = "my";
let d = "name";
let e = "Tom";
// edit result to achieve the expected
output
let result = '';
console.log(result);
//expected output
"Hello, my name is Tom"
let a = "1";
let b = "2";
let c = "plus";
90
let d = "3";
let e = "equals";
// edit result to use template literals
let result = a + " " + c + " " + b + " " +
e + " " + d;
console.log(result);
// 1 plus 2 equals 3
91
Chapter 5: Additional string
methods
There are many methods that we can use against
strings. Here's a list of a few of them:
indexOf()
slice()
toUpperCase()
92
toLowerCase()
• startsWith()
• endsWith()
• includes()
• repeat()
startsWith()
93
code.startsWith("ABB");
// false
code.startsWith("abc");
// false, startsWith is case sensitive
code.startsWith("ABC");
// true
endsWith()
94
code.endsWith("DEF");
// true
includes()
95
repeat()
96
End of Chapter 5 Quiz
5.1 What is the correct output of the following
code?
true
false
true
false
98
Chapter 6: Destructuring
MDN defines destructuring like this:
Destructuring Objects
To create variables from an object, we used to do the
following:
var person = {
first: "Alberto",
last: "Montalesi"
}
var first = person.first;
var last = person.last;
const person = {
first: "Alberto",
last: "Montalesi"
99
}
const { first, last } = person;
const person = {
name: "Alberto",
last: "Montalesi",
links:{
social: {
facebook: "https://www.facebook.com/
alberto.montalesi",
},
website: "http://
albertomontalesi.github.io/"
}
}
const { facebook } = person.links.social;
100
We are not limited to name our variable the same as
the property of the object. We can also rename as the
following:
const { facebook:fb } =
person.links.social;
// it will look for the property
person.links.social.facebook and name the
variable fb
console.log(fb); // https://
www.facebook.com/alberto.montalesi
console.log(facebook); //ReferenceError:
facebook is not defined
101
Destructuring Arrays
102
// Array [ "pizza", "ice cream", "cheese
cake" ]
103
End of Chapter 6 Quiz
6.1 Write the code to accomplish the following
task:
105
Chapter 7: Iterables and looping
The for of loop
const fruits =
['apple','banana','orange'];
for(const fruit of fruits){
106
console.log(fruit);
}
// apple
// banana
// orange
const car = {
maker: "BMW",
color: "red",
year : "2010",
}
for (const prop of Object.keys(car)){
const value = car[prop];
console.log(prop,value);
}
// maker BMW
107
// color red
// year 2010
const car = {
maker: "BMW",
color: "red",
year : "2010",
}
for (const prop in car){
console.log(prop, car[prop]);
}
// maker BMW
108
// color red
// year 2010
109
End of Chapter 7 Quiz
7.1 Which one of these loops was introduced
in ES6?
while
for of
for in
Tom Jerry
Tom
Mickey
110
Chapter 8: Array improvements
Array.from()
<div class="fruits">
<p> Apple </p>
<p> Banana </p>
<p> Orange </p>
</div>
const fruits =
document.querySelectorAll(".fruits p");
// fruits is a nodelist (an array-like
collection) containng our three p tags
// now we convert it in an Array
const fruitArray = Array.from(fruits);
console.log(fruitArray);
// [p,p,p]
//since now we are dealing with an array we
can use map
111
const fruitNames = fruitArray.map( fruit =>
fruit.textContent);
console.log(fruitNames);
// ["Apple", "Banana", "Orange"]
const fruits =
Array.from(document.querySelectorAll(".frui
ts p"));
const fruitNames = fruits.map(fruit =>
fruit.textContent);
console.log(fruitNames);
// ["Apple", "Banana", "Orange"]
const fruits =
document.querySelectorAll(".fruits p");
const fruitArray = Array.from(fruits, fruit
=> {
console.log(fruit);
112
// <p> Apple </p>
// <p> Banana </p>
// <p> Orange </p>
return fruit.textContent;
// we only want to grab the content not
the whole tag
});
console.log(fruitArray);
// ["Apple", "Banana", "Orange"]
Array.of()
113
Array.find()
Array.findIndex()
const greetings =
["hello","hi","byebye","goodbye","hi"];
114
let foundIndex = greetings.findIndex(e => e
=== "hi");
console.log(foundIndex);
// 1
115
Simply put, the first condition is true, because there
are some elements greater than 2, but the second is
false because not every element is greater than 2.
116
End of Chapter 8 Quiz
8.1 Write the code to accomplish the following
task:
4,5
117
8.3 What is the correct output of the following
code?
false
true
[1,2,3]
[1,4,9]
[1,3,5]
118
Chapter 9: Spread operator and
rest parameters
The Spread operator
According to MDN:
Combine arrays
const veggie =
["tomato","cucumber","beans"];
const meat = ["pork","beef","chicken"];
const menu = [...veggie, "pasta", ...meat];
console.log(menu);
// Array [ "tomato", "cucumber", "beans",
"pasta", "pork", "beef", "chicken" ]
119
and put them inside the array menu and at the same
time add a new item in between them.
Copy arrays
const veggie =
["tomato","cucumber","beans"];
const newVeggie = veggie;
// this may seem like we created a copy of
the veggie array but look now
veggie.push("peas");
console.log(veggie);
// Array [ "tomato", "cucumber", "beans",
"peas" ]
console.log(newVeggie);
// Array [ "tomato", "cucumber", "beans",
"peas" ]
120
The following is how we would usually make a copy of
an array in ES5 and earlier
const veggie =
["tomato","cucumber","beans"];
// we created an empty array and put the
values of the old array inside of it
const newVeggie = [].concat(veggie);
veggie.push("peas");
console.log(veggie);
// Array [ "tomato", "cucumber", "beans",
"peas" ]
console.log(newVeggie);
// Array [ "tomato", "cucumber", "beans" ]
const veggie =
["tomato","cucumber","beans"];
const newVeggie = [...veggie];
veggie.push("peas");
console.log(veggie);
// Array [ "tomato", "cucumber", "beans",
"peas" ]
console.log(newVeggie);
// Array [ "tomato", "cucumber", "beans" ]
121
The syntax for the Spread operator is the
following ...YourArray. Since we wanted the
variable newVeggie to be a copy of the array veggie
we assigned it to an Array and inside of it we spread
all the values from the variable veggie like so:
[...veggie].
// OLD WAY
function doStuff (x, y, z) {
console.log(x + y + z);
}
var args = [0, 1, 2];
// Call the function, passing args
doStuff.apply(null, args);
// USE THE SPREAD SYNTAX
doStuff(...args);
// 3 (0+1+2);
console.log(args);
// Array [ 0, 1, 2 ]
122
As you can see, in the example, our doStuff function
accepts 3 parameters and we are passing them by
spreading the array args into the function like
so: ...args replacing the need of resorting to
use .apply().
123
In the example given above, we provided three values
inside the array but we only have two arguments in
our function therefore the last one is left out.
let person = {
name : "Alberto",
surname: "Montalesi",
age: 25,
}
let clone = {...person};
console.log(clone);
// Object { name: "Alberto", surname:
"Montalesi", age: 25 }
124
The Rest parameter
const runners = ["Tom", "Paul", "Mark",
"Luke"];
const [first,second,...losers] = runners;
console.log(...losers);
// Mark Luke
125
End of Chapter 9 Quiz
9.1 What is the correct syntax to spread the
values of an array?
[.]
(...)
[...]
{...}
const veggie =
["tomato","cucumber","beans"];
const meat = ["pork","beef","chicken"];
126
9.3 Write the code to achieve the following
task:
[1, 2, 3, 4]
[1, 2, 4, 5]
[1, 2, 3, 4, 5]
"1, 2, 3, 4, 5"
127
Chapter 10: Object literal
upgrades
In this article we will look at the many upgrades
brought by ES6 to the Object literal notation.
const person = {
name: name,
surname: surname,
age: age,
nationality: nationality,
}
console.log(person);
128
// { name: 'Alberto',
// surname: 'Montalesi',
// age: 25,
// nationality: 'Italian' }
const person = {
name,
surname,
age,
nationality,
}
console.log(person);
// {name: "Alberto", surname: "Montalesi",
age: 25, nationality: "Italian"}
const person = {
name: "Alberto",
greet: function(){
129
console.log("Hello");
},
}
person.greet();
// Hello
const person = {
name: "Alberto",
greet(){
console.log("Hello");
},
}
person.greet();
// Hello;
130
const person1 = {
() => console.log("Hello"),
};
const person2 = {
greet: () => console.log("Hello"),
}
person2.greet()
// Hello
131
can do both things at the same time. Take a look at
the following example:
132
End of Chapter 10 Quiz
10.1 Refactor the code to make it more
concise:
const animal = {
name: name,
age: age,
breed: breed,
}
name
"Alberto"
myname
"name"
133
const person = {
name,
age,
color
};
console.log(person.color);
"Green"
color
favoriteColor
134
Chapter 11: Symbols
ES6 added a new type of primitive called Symbols.
What are they? And what do they do?
const me = Symbol("Alberto");
console.log(me);
// Symbol(Alberto)
const me = Symbol("Alberto");
console.log(me);
// Symbol(Alberto)
const clone = Symbol("Alberto");
console.log(clone);
// Symbol(Alberto)
135
console.log(me == clone);
// false
console.log(me === clone);
// false
They both have the same value, but we will never have
naming collisions with Symbols as they are always
unique.
const office = {
"Tom" : "CEO",
"Mark": "CTO",
"Mark": "CIO",
}
for (person in office){
console.log(person);
}
// Tom
// Mark
136
Here we have our office object with 3 people, two of
which share the same name.
To avoid naming collisions we can use symbols.
const office = {
[Symbol("Tom")] : "CEO",
[Symbol("Mark")] : "CTO",
[Symbol("Mark")] : "CIO",
}
for(person in office) {
console.log(person);
}
// undefined
const office = {
[Symbol("Tom")] : "CEO",
[Symbol("Mark")] : "CTO",
[Symbol("Mark")] : "CIO",
};
137
const symbols =
Object.getOwnPropertySymbols(office);
console.log(symbols);
// 0: Symbol(Tom)
// 1: Symbol(Mark)
// 2: Symbol(Mark)
// length: 3
const symbols =
Object.getOwnPropertySymbols(office);
const value = symbols.map(symbol =>
office[symbol]);
console.log(value);
// 0: "CEO"
// 1: "CTO"
// 2: "CIO"
// length: 3
138
End of Chapter 11 Quiz
11.1 What is a symbol?
a caveman
a property
a primitive
a type of function
const friends = {
"Tom" : "bff",
"Jim" : "brother",
"Tom" : "cousin",
}
139
for (friend in friends){
console.log(friend);
}
Jim Tom
Error
Tom Jim
const family = {
[Symbol("Tom")] : "father",
[Symbol("Jane")] : "mother",
[Symbol("Tom")] : "brother",
};
const symbols =
Object.getOwnPropertySymbols(family);
console.log(symbols);
Symbol(Tom) Symbol(Jane)
undefined
Symbol(Jane) Symbol(Tom)
140
Chapter 12: classes
Quoting MDN:
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function(){
console.log("Hello, my name is " +
this.name);
}
const alberto = new Person("Alberto", 26);
const caroline = new Person("Caroline",26);
alberto.greet();
// Hello, my name is Alberto
141
caroline.greet();
// Hello, my name is Caroline
Create a class
There are two ways of creating a class:
• class declaration
• class expression
// class declaration
class Person {
}
// class expression
const person = class Person {
}
142
ReferenceError you need to declare your class before
you access it.
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
greet(){
console.log(`Hello, my name is $
{this.name} and I am ${this.age} years old`
);
} // no commas in between methods
farewell(){
console.log("goodbye friend");
}
}
const alberto = new Person("Alberto",26);
alberto.greet();
143
// Hello, my name is Alberto and I am 26
years old
alberto.farewell();
// goodbye friend
Static methods
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
static info(){
console.log("I am a Person class, nice
to meet you");
}
}
144
const alberto = new Person("Alberto",26);
alberto.info();
// TypeError: alberto.info is not a
function
Person.info();
// I am a Person class, nice to meet you
class Person {
constructor(name,surname) {
this.name = name;
this.surname = surname;
this.nickname = "";
}
set nicknames(value){
this.nickname = value;
console.log(this.nickname);
}
get nicknames(){
console.log(`Your nickname is $
145
{this.nickname}`);
}
}
const alberto = new
Person("Alberto","Montalesi");
// first we call the setter
alberto.nicknames = "Albi";
// "Albi"
// then we call the getter
alberto.nicknames;
// "Your nickname is Albi"
146
}
greet(){
console.log(`Hello, my name is $
{this.name} and I am ${this.age} years old`
);
}
}
// our new class
class Adult extends Person {
constructor(name,age,work){
this.name = name;
this.age = age;
this.work = work;
}
}
const alberto = new
Adult("Alberto",26,"software developer");
147
ReferenceError: must call super
constructor before using |this| in Adult
class constructor
148
}
greet(){
console.log(`Hello, my name is $
{this.name} and I am ${this.age} years old`
);
}
}
// our new class
class Adult extends Person {
constructor(name,age,work){
super(name,age);
this.work = work;
}
}
const alberto = new
Adult("Alberto",26,"software developer");
console.log(alberto.age);
// 26
console.log(alberto.work);
// "software developer"
alberto.greet();
149
// Hello, my name is Alberto and I am 26
years old
Extending Arrays
150
// we use spread to place all the
students in the array individually
otherwise we would push an array into an
array
super(...students);
this.name = name;
// we create a new method to add
students
}
add(student){
this.push(student);
}
}
const my`class` = new `class`room('1A',
{name: "Tim", mark: 6},
{name: "Tom", mark: 3},
{name: "Jim", mark: 8},
{name: "Jon", mark: 10},
);
// now we can call
my`class`.add({name: "Timmy", mark:7});
my`class`[4];
// Object { name: "Timmy", mark: 7 }
151
// we can also loop over with for of
for(const student of my`class`) {
console.log(student);
}
// Object { name: "Tim", grade: 6 }
// Object { name: "Tom", grade: 3 }
// Object { name: "Jim", grade: 8 }
// Object { name: "Jon", grade: 10 }
// Object { name: "Timmy", grade: 7 }
152
End of Chapter 12 Quiz
12.1 What is a class?
a new primitive
153
12.4 What is the correct output of the
following code?
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
}
class Adult extends Person {
constructor(work){
this.work = work;
}
}
const my = new Adult('software developer');
console.log(my.work);
"software developer"
154
12.5 Write the code to accomplish the
following task:
155
Chapter 13: Promises
JavaScript work synchronously which means that
each block of code will be executed after the previous
one.
Callback hell
157
}
}
}
What is a Promise?
From MDN:
158
Create your own promise
159
We can combine a setTimeout() to wait a certain
amount of time before resolving.
160
reject(Error("this is our error"));
}, 2000);
});
myPromise
.then(data => {
console.log(data);
})
.catch(err => {
console.error(err);
})
// Error: this is our error
// Stack trace:
// myPromise</<@debugger eval code:3:14
Chaining promises
161
for the subsequent one, whether the promise was
resolved or rejected.
162
// failed!
})
//Promise.resolve()
Promise.resolve('Success').then(function(va
lue) {
console.log();
// "Success"
}, function(value) {
cnsole.log('fail')
});
// Promise.reject()
Promise.reject(new
Error('fail')).then(function() {
// not called
}, function(error) {
console.log(error);
// Error: fail
});
164
As you can see in the first example, the Promise
created in the then clause has two arguments, one
function that get's called when the Promise resolves,
and one that gets called when the Promise rejects.
Since Promise.resolve() immediately resolves the
promise, the first functions is being called.
167
// one of the two promises will fail, but
`.all` will return only a rejection.
Promise
.all([promise1, promise2])
.then(data => {
const[promise1data, promise2data] =
data;
console.log(promise1data,
promise2data);
})
.catch(err => {
console.log(err);
});
// Error: oooops error
168
setTimeout(resolve, 100, 'second value');
});
Promise.race([promise1,
promise2]).then(function(value) {
console.log(value);
// Both resolve, but promise2 is faster
});
// expected output: "second value"
169
End of Chapter 13 Quiz
13.1 What is a Promise?
a new primitive
Promise.some()
Promise.all()
Promise.reject()
function myPromise(){
return new Promise((resolve,reject) =>
170
{
reject();
})
}
myPromise()
.then(() => {
console.log('1')
})
.then(() => {
console.log('2')
})
.catch(() => {
console.log('3')
})
.then(() => {
console.log('4')
});
1,2,3,4
3,4,1,2
3,4
171
Chapter 14: Generators
What is a Generator?
function* fruitList(){
yield 'Banana';
yield 'Apple';
yield 'Orange';
}
const fruits = fruitList();
fruits;
// Generator
fruits.next();
// Object { value: "Banana", done: false }
fruits.next();
// Object { value: "Apple", done: false }
fruits.next();
// Object { value: "Orange", done: false }
172
fruits.next();
// Object { value: undefined, done: true }
173
}
}
const fruitGenerator = loop(fruitList);
fruitGenerator.next();
// Object { value: "I like to eat Bananas",
done: false }
fruitGenerator.next();
// Object { value: "I like to eat Apples",
done: false }
fruitGenerator.next().value;
// "I like to eat Oranges"
• Our new generator will loop over the array and print
one value at a time every time we call .next()
function* fruitList(){
yield 'Banana';
174
yield 'Apple';
yield 'Orange';
}
const fruits = fruitList();
fruits.return();
// Object { value: undefined, done: true }
function* gen(){
try {
yield "Trying...";
yield "Trying harder...";
yield "Trying even harder..";
}
catch(err) {
console.log("Error: " + err );
}
}
const myGenerator = gen();
175
myGenerator.next();
// Object { value: "Trying...", done: false
}
myGenerator.next();
// Object { value: "Trying harder...",
done: false }
myGenerator.throw("ooops");
// Error: ooops
// Object { value: undefined, done: true }
176
Using a Generator in combination with a Promise
will allow us to write asynchronous code that feels like
synchronous code.
177
resolve
// {value: Promise, done: false}
val1.value.then(() => {
console.log(asyncFunc.next());
})
// Object { value: "our value is... 2",
done: false }
178
End of Chapter 14 Quiz
14.1 What is the correct syntax of a generator
function?
generator function() {...}
new generator(){...}
function*(){...}
It can't be overwritten
function* fruitList(){
yield 'Banana';
yield 'Apple';
yield 'Pomelo';
yield 'Mangosteen';
yield 'Orange';
}
179
const fruits = fruitList();
fruits;
fruits.next();
fruits.next();
fruits.next();
function* fruitList(){
yield 'Banana';
yield 'Apple';
yield 'Orange';
}
const fruits = fruitList();
180
fruits.return();
181
Chapter 15: Proxies
What is a Proxy?
From MDN:
// our object
const dog = { breed: "German Shephard",
age: 5}
// our Proxy
const dogProxy = new Proxy(dog, {
get(target,breed){
return target[breed].toUpperCase();
182
},
set(target, breed, value){
console.log("changing breed to...");
target[breed] = value;
}
});
console.log(dogProxy.breed);
// "GERMAN SHEPHARD"
console.log(dogProxy.breed = "Labrador")
// changing breed to...
// "Labrador"
console.log(dogProxy.breed);
// "LABRADOR"
const validateAge = {
set: function(object,property,value){
if(property === 'age'){
183
if(value < 18){
throw new Error('you are too
young!');
} else {
// default behaviour
object[property] = value;
return true
}
}
}
}
const user = new Proxy({},validateAge)
user.age = 17
// Uncaught Error: you are too young!
user.age = 21
// 21
184
Proxy we need to define only one getter and one
setter. Let's look at this example:
const dog = {
_name: 'pup',
_age: 7,
get name() {
console.log(this._name)
},
get age(){
console.log(this._age)
},
set name(newName){
this._name = newName;
console.log(this._name)
},
set age(newAge){
this._age = newAge;
console.log(this._age)
}
}
dog.name;
// pup
185
dog.age;
// 7
dog.breed;
// undefined
dog.name = 'Max';
// Max
dog.age = 8;
// 8
set name(newName){
this.name = newName;
}
186
set rename(newName){
this.name = newName;
}
const dog = {
name: 'pup',
age: 7
}
const handler = {
get: (target, property) => {
property in target ?
console.log(target[property]) :
console.log('property not found');
},
set: (target, property, value) => {
target[property] = value;
console.log(target[property])
}
}
187
const dogProxy = new Proxy(dog, handler);
dogProxy.name;
// pup
dogProxy.age;
// 7
dogProxy.name = 'Max';
// Max
dogProxy.age = 8;
// 8
dogProxy.breed;
// property not found
188
• shorter, cleaner code
189
End of Chapter 15 Quiz
15.1 What is the use of a Proxy?
to store unique values
190
Chapter 16: Sets, WeakSets, Maps
and WeakMaps
What is a Set?
191
As you can see, at the end we tried to add "Dad"
again, but the Set still remained the same because a
Set can only take unique values.
family.size;
// 3
family.keys();
// SetIterator {"Dad", "Mom", "Son"}
family.entries();
// SetIterator {"Dad", "Mom", "Son"}
family.values();
// SetIterator {"Dad", "Mom", "Son"}
family.delete("Dad");
family;
// Set [ "Mom", "Son" ]
family.clear();
family;
// Set []
192
Loop over a Set
// using `.next()`
const iterator = family.values();
iterator.next();
// Object { value: "Dad", done: false }
iterator.next();
// Object { value: "Mom", done: false }
// using a `for of` loop
for(const person of family) {
console.log(person);
}
// Dad
// Mom
// Son
193
Remove duplicates from an array
As you can see the new array only contains the unique
values from the original array.
194
What is a WeakSet?
195
// WeakSet [ {…}, {…} ]
// wait a few seconds
console.log(family);
// WeakSet [ {…} ]
What is a Map?
196
family.forEach((val,key) =>
console.log(key,val));
// Dad 40
// Mom 50
// Son 20
for(const [key,val] of family){
console.log(key,val);
}
// Dad 40
// Mom 50
// Son 20
What is a WeakMap?
A WeakMap is a collection of key/value pairs and
similarly to a WeakSet, even in a WeakMap the keys are
weakly referenced, which means that when the
reference is lost, the value will be removed from the
WeakMap and garbage collected.
197
A WeakMap is not enumerable therefore we cannot
loop over it.
198
End of Chapter 16 Quiz
16.1 Which one of these does not exist?
Set
WeakSet
StrongSet
WeakMap
199
Chapter 17: Everything new in
ES2016
ES2016 introduced only two new features:
• Array.prototype.includes()
Array.prototype.includes()
200
let array = [1,3,5,7,9,11];
array.includes(3,1);
// find the number 3 starting from array
index 1
// true
array.includes(5,4);
//false
array.includes(1,-1);
// find the number 1 starting from the
ending of the array going backwards
// false
array.includes(11,-3);
// true
Math.pow(2,2);
// 4
Math.pow(2,3);
// 8
2**2;
// 4
2**3;
// 8
2**2**2;
// 16
Math.pow(Math.pow(2,2),2);
// 16
Array.prototype.has()
Array.prototype.includes()
Array.prototype.find()
true
false
203
Math.pow(Math.pow(2,2),2);
// 16
204
Chapter 18: ES2017 string
padding, Object.entries(),
Object.values() and more
ES2017 introduced many cool new features, which we
are going to see here.
"hello".padStart(6);
// " hello"
"hello".padEnd(6);
// "hello "
"hi".padStart(10);
// 10 - 2 = 8 empty spaces
205
// " hi"
"welcome".padStart(10);
// 10 - 6 = 4 empty spaces
// " welcome"
206
that we now have all of them perfectly aligned to the
right.
"hello".padEnd(13," Alberto");
// "hello Alberto"
"1".padStart(3,0);
// "001"
"99".padStart(3,0);
// "099"
const family = {
father: "Jonathan Kent",
mother: "Martha Kent",
son: "Clark Kent",
}
207
Object.keys(family);
// ["father", "mother", "son"]
family.father;
"Jonathan Kent"
Object.values(family);
// ["Jonathan Kent", "Martha Kent", "Clark
Kent"]
Object.entries(family);
// ["father", "Jonathan Kent"]
// ["mother", "Martha Kent"]
// ["son", "Clark Kent"]
Object.getOwnPropertyDescriptors()
Trailing commas
// from this
const object = {
prop1: "prop",
209
prop2: "propop"
}
// to this
const object = {
prop1: "prop",
prop2: "propop",
}
// I write
const object = {
prop1: "prop",
prop2: "propop"
}
// my colleague updates the code, adding a
new property
const object = {
prop1: "prop",
prop2: "propop"
prop3: "propopop"
210
}
// suddenly, he gets an error because he
did not notice that I forgot to leave a
comma at the end of the last parameter.
From MDN:
• add / sub
• and / or / xor
• load / store
211
Atomics are used with SharedArrayBuffer (generic
fixed-length binary data buffer) objects which
represent generic, fixed-length raw binary data buffer.
// create a `SharedArrayBuffer`
const buffer = new SharedArrayBuffer(16);
const uint8 = new Uint8Array(buffer);
// add a value at the first position
uint8[0] = 10;
console.log(Atomics.add(uint8, 0, 5));
// 10
// 10 + 5 = 15
console.log(uint8[0])
// 15
console.log(Atomics.load(uint8,0));
// 15
212
As you can see, calling Atomics.add() will return the
previous value at the array position we are targeting.
when we call again uint8[0] we see that the addition
was performed and we got 15.
// create a `SharedArrayBuffer`
const buffer = new SharedArrayBuffer(16);
const uint8 = new Uint8Array(buffer);
// add a value at the first position
uint8[0] = 10;
console.log(Atomics.sub(uint8, 0, 5));
// 10
// 10 - 5 = 5
console.log(uint8[0])
// 5
console.log(Atomics.store(uint8,0,3));
// 3
213
console.log(Atomics.load(uint8,0));
// 3
214
End of Chapter 18 Quiz
18.1 What is the correct output of the
following code?
"hello".padStart(6);
" hello"
"hello "
" hello"
"hello"
215
18.3 Which of the following was not added in
ES2016?
Object.entries()
Object.keys()
Object.values()
10
15
216
uint8[0] = 10;
Atomics.sub(uint8, 0, 6);
console.log(Atomics.load(uint8,0));
10
217
Chapter 19: ES2017 Async and
Await
ES2017 introduced a new way of working with
promises, called "async/await".
Promise review
Before we dive in this new syntax let's quickly review
how we would usually write a promise:
218
Let's see a different example:
function walk(amount) {
return new Promise((resolve,reject) => {
if (amount < 500) {
reject ("the value is too small");
}
setTimeout(() => resolve(`you walked
for ${amount}ms`),amount);
});
}
walk(1000).then(res => {
console.log(res);
return walk(500);
}).then(res => {
console.log(res);
return walk(700);
}).then(res => {
console.log(res);
return walk(800);
}).then(res => {
console.log(res);
return walk(100);
}).then(res => {
console.log(res);
219
return walk(400);
}).then(res => {
console.log(res);
return walk(600);
});
// you walked for 1000ms
// you walked for 500ms
// you walked for 700ms
// you walked for 800ms
// uncaught exception: the value is too
small
function walk(amount) {
return new Promise((resolve,reject) => {
if (amount < 500) {
reject ("the value is too small");
}
setTimeout(() => resolve(`you walked
for ${amount}ms`),amount);
});
220
}
// create an async function
async function go() {
// use the keyword `await` to wait for
the response
const res = await walk(500);
console.log(res);
const res2 = await walk(900);
console.log(res2);
const res3 = await walk(600);
console.log(res3);
const res4 = await walk(700);
console.log(res4);
const res5 = await walk(400);
console.log(res5);
console.log("finished");
}
go();
// you walked for 500ms
// you walked for 900ms
// you walked for 600ms
// you walked for 700ms
221
// uncaught exception: the value is too
small
222
// use await in the top-level code
let response = Promise.resolve("hi");
let result = await response;
// SyntaxError: await is only valid in
async functions and async generators
Error handling
223
asyncFunc();
// TypeError: failed to fetch
224
End of Chapter 19 Quiz
19.1 What is the correct output of the
following code?
function func() {
let promise = Promise.resolve(1);
let result = await promise;
}
func();
true
undefined
SyntaxError
function walk(amount) {
return new Promise((resolve,reject) => {
if (amount > 500) {
reject ("the value is too big");
}
setTimeout(() => resolve(`you walked
for ${amount}ms`),amount);
});
225
}
async function go() {
const res = await walk(500);
console.log(res);
const res2 = await walk(300);
console.log(res2);
const res3 = await walk(200);
console.log(res3);
const res4 = await walk(700);
console.log(res4);
const res5 = await walk(400);
console.log(res5);
console.log("finished");
}
go();
"finished"
226
Chapter 20: ES2018 Async
Iteration and more?
In this chapter we will look at what was introduced
with ES2018.
const veggie =
["tomato","cucumber","beans"];
const meat = ["pork","beef","chicken"];
const menu = [...veggie, "pasta", ...meat];
console.log(menu);
// Array [ "tomato", "cucumber", "beans",
"pasta", "pork", "beef", "chicken" ]
let myObj = {
a:1,
b:3,
c:5,
d:8,
227
}
// we use the rest operator to grab
everything else left in the object.
let { a, b, ...z } = myObj;
console.log(a); // 1
console.log(b); // 3
console.log(z); // {c: 5, d: 8}
// using the spread syntax we cloned our
Object
let clone = { ...myObj };
console.log(clone);
// {a: 1, b: 3, c: 5, d: 8}
myObj.e = 15;
console.log(clone)
// {a: 1, b: 3, c: 5, d: 8}
console.log(myObj)
// {a: 1, b: 3, c: 5, d: 8, e: 15}
228
Asynchronous Iteration
With Asynchronous Iteration we can iterate
asynchronously over our data.
229
Each time we access the next value in the sequence,
we implicitly await the promise returned from the
iterator method.
Promise.prototype.finally()
230
Promises will fulfill based on the Promise they were
chained onto.
231
RegExp features
Four new RegExp related features made it to the new
version of ECMAScript. They are:
/foo.bar/s.test('foo\nbar');
// true
232
refactor. For example, given/(\d{4})-(\d{2})-
(\d{2})/ that matches a date, one cannot be sure
which group corresponds to the month and which one
is the day without examining the surrounding code.
Also, if one wants to swap the order of the month and
the day, the group references should also be updated.
A capture group can be given a name using the (?
<name>...) syntax, for any identifier name. The
regular expression for a date then can be written as /
(?<year>\d{4})-(?<month>\d{2})-(?
<day>\d{2})/u. Each name should be unique and
follow the grammar for ECMAScript IdentifierName.
Named groups can be accessed from properties of a
groups property of the regular expression result.
Numbered references to the groups are also created,
just as for non-named groups. For example:
let re = /(?<year>\d{4})-(?<month>\d{2})-
(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';
// result[0] === '2015-01-02';
// result[1] === '2015';
// result[2] === '01';
// result[3] === '02';
233
let {groups: {one, two}} = /^(?<one>.*):(?
<two>.*)$/u.exec('foo:bar');
console.log(`one: ${one}, two: ${two}`);
// one: foo, two: bar
234
RegExp Unicode Property Escapes
const regexGreekSymbol = /
\p{Script=Greek}/u;
regexGreekSymbol.test('π');
// true
235
End of Chapter 20 Quiz
20.1 What is the correct syntax for the spread
operator for objects?
[...]
(...)
{...}
=>
let myObj = {
a:1,
b:2,
c:3,
d:4,
}
let { a, b, ...z } = myObj;
console.log(z);
[3,4]
{c:3, d:4}
undefined
[c,d]
236
20.3 What is the correct output of the
following code:
1,2
237
Chapter 21: What's new in
ES2019?
In this chapter we will look at what is included in the
latest version of ECMAScript: ES2019.
Array.prototype.flat() /
Array.prototype.flatMap()
239
As you can see, if we use .map() we will get a multi
level array, a problem that we can solve by
using .flatMap() which will also flatten our array.
Object.fromEntries()
const keyValueArray = [
['key1', 'value1'],
['key2', 'value2']
]
const obj =
Object.fromEntries(keyValueArray)
// {key1: "value1", key2: "value2"}
240
String.prototype.trimStart() / .trimEnd()
String.prototype.trimStart() removes white
space from the beginning of a string while
String.prototype.trimEnd() removes them from
the end.
241
Optional Catch Binding
Prior to ES2019 you had to always include an
exception variable in your catch clause. E2019 allows
you to omit it.
// Before
try {
...
} catch(error) {
...
}
// ES2019
try {
...
} catch {
...
}
242
Function.prototype.toString()
function sum(a, b) {
return a + b;
}
console.log(sum.toString());
// function sum(a, b) {
// return a + b;
// }
function sum(a, b) {
// perform a sum
return a + b;
}
console.log(sum.toString());
// function sum(a, b) {
// // perform a sum
// return a + b;
// }
243
Symbol.prototype.description
const me = Symbol("Alberto");
me.description;
// "Alberto"
me.toString()
// "Symbol(Alberto)"
244
End of Chapter 21 Quiz
21.1 Transform the following
multidimensional array into a single
dimensional array in one line of code using
the new Array method introduced in ES2019
const keyValueArray = [
['key1', 'value1'],
['key2', 'value2']
]
// expected: {key1: "value1", key2:
"value2"}
const me = Symbol("Alberto");
console.log(me.description);
245
Symbol
Symbol(Alberto)
"Alberto"
undefined
Function
"a + b"
246
sum
247
An Intro To TypeScript
Now that you have a clear idea of how JavaScript
looks like in 2019, I think it's a good moment to
introduce you TypeScript.
function getUserByID(userID){
// perform an api call to your server to
retrieve a user by its id
}
248
That is where TypeScript comes to help. This is how
the same code would look like:
function getUserByID(userID:number){
// perform an api call to your server to
retrieve a user by its id
}
What is TypeScript?
Created just a few year ago by Microsoft, TypeScript
is a typed superset of JavaScript that compiles to
plain JavaScript.
249
How to use TypeScript
Getting started with TypeScript takes literally 5
minutes.
Next you can open your code editor and create a file
called greeter.ts (NOT .js).
tsc greeter.ts
250
greeter('Alberto');
// hello Alberto
• boolean
• number
• string
• Array
• object
• Tuple
• enum
251
• any
• void
• never
boolean
number
string
252
Array
Array<{label:string,value:string}> simply
means that the argument is an Array of objects with
properties of label and value, both of type string.
253
object
function greetUser(user:
{name:string,age:number}){
console.log(`hello ${user.name}`)
}
greetUser({name: 'Alberto', age:27});
// hello Alberto
254
looks at the code to know what they can and what
they cannot do with that object.
Tuple
enum
255
console.log(blogPostStatus);
// 2
256
enum Status {deleted = -1, pending,
active}
console.log(Status[0]);
// pending
any
257
We expect both variable to be of type object but we
are not sure of their properties, therefore we use any.
void
function
storeValueInDatabase(objectToStore): void {
// store your value in the database
}
258
When talking about union types you will see the use of
these two types.
never
259
interface Car {
wheels: number;
color: string;
brand: string;
}
interface Car {
wheels: number;
color: string;
brand: string;
coupe?: boolean;
}
interface Car {
readonly wheels: number;
color: string;
260
brand: string;
coupe?: boolean;
}
interface Greet {
(greeting: string, name: string): string
}
let greetingFunction: Greet;
greetingFunction = (greeting: string, name:
string): string => {
console.log(`${greeting} ${name}`);
return `${greeting} ${name}`;
}
greetingFunction('Bye','Alberto');
interface Vehicle {
wheels: number;
color: string;
}
interface Airplane extends Vehicle {
wings: number;
rotors: number;
}
Classes
262
class Animal {
eat = ()=> {
console.log('gnam gnam');
}
sleep = () => {
console.log('zzzz');
}
}
class Human extends Animal {
work = ()=> {
console.log('zzzzzzz');
}
}
const me = new Human();
me.work();
// zzzzzzz
me.eat();
// gnam gnam
me.sleep()
// zzzz
263
A difference with ES6 classes is that TypeScript
allows us to define the way that class members will be
accessed from our application.
class Animal {
public eat = ()=> {
console.log('gnam gnam')
}
public sleep = () => {
console.log('zzzz')
}
}
const dog = new Animal();
dog.eat();
// gnam gnam
class Animal {
public eat = ()=> {
264
console.log('gnam gnam')
}
public sleep = () => {
console.log('zzzz')
}
}
class Human extends Animal {
private work = ()=> {
console.log('zzzzzzz')
}
}
const me = new Human();
me.work();
// Property 'work' is private and only
accessible within class 'Human'
class Human {
protected work = ()=> {
console.log('zzzzzzz')
}
}
265
class Adult extends Human {
public doWork = () => {
console.log(this.work)
}
}
Intersection Types
interface Person {
sex: 'male' | 'female' | 'N/A'
age:number,
}
interface Worker {
266
job: string
}
type Adult = Person & Worker;
const me: Adult = {
sex: 'male',
age: 27,
job: 'software developer'
}
console.log(me);
// { sex: 'male', age: 27, job: 'software
developer' }
Union Types
267
Another example may be:
interface Kid {
age:number
}
interface Adult {
age: number,
job: string
}
function person(): Kid | Adult {
return { age: 27 }
}
const me = person();
me.age // ok
me.job // error
268
269
Conclusion
270
TypeScript Quiz
TS-01 Which one of these is not a real basic
type of TypeScript?
Tuple
void
enum
every
const x = 0xf00d;
string
void
hex
number
271
TS-04 What is the correct output of the
following code?
"second"
{second:1}
true
272
Conclusion
I sincerely thank you for making it this far. This is my
first book and knowing that somebody read it all fills
me with joy.
Thank you very much for your time and your support.
273
Quiz Solutions
Introduction to JavaScript solutions
JS-01
JS-02
• Object
JS-03
JS-04
• false
JS-05
274
End of Chapter 1 Quiz Solutions
1.1
• Good morning
1.2
• 2
1.3
• 100
1.4
• ReferenceError
2.1
• B
275
2.2
• 10
2.3
(arg) => {
console.log(arg);
}
3.1
276
3.2
• 10
4.1
4.2
4.3
277
End of Chapter 5 Quiz
5.1
• true
5.2
• false
5.3
6.1
278
// no
console.log(full);
// yes
6.2
7.1
• for of
7.2
279
End of Chapter 8 Quiz
8.1
Array.from(apple);
8.2
• 4
8.3
• true
8.4
• [1,4,9]
280
End of Chapter 9 Quiz
9.1
• [...]
9.2
9.3
9.4
• [1, 2, 3, 4, 5]
281
End of Chapter 10 Quiz
10.1
const animal = {
name,
age,
breed,
}
10.2
• "Alberto"
10.3
• color is not defined
11.1
• a primitive
282
11.2
11.3
• Tom Jim
11.4
12.1
283
12.2
12.3
12.4
12.5
284
this.work = work;
}
}
13.1
13.2
13.3
• Promise.some()
285
13.4
• 3,4
14.1
• function*(){...}
14.2
14.3
286
The last output of fruits.next(); is Object
{ value: "Pomelo", done: false }. Be careful
that done is set to false and not true.
14.4
• Object { value: undefined, done: true }
15.1
From MDN:
15.2
• 2
287
A Proxy can take a handler and a target
15.3
16.1
• StrongSet
16.2
16.3
288
End of Chapter 17 Quiz
17.1
• Array.prototype.includes()
17.2
• false
17.3
2**2**2;
// 16
18.1
• " hello"
289
18.2
strings.forEach(str =>
console.log(str.padStart(16)));
18.3
• Object.keys()
18.4
• 10
18.5
• 4
19.1
• SyntaxError
290
Remember: await is only valid in async functions
and async generators
19.2
20.1
• {...}
20.2
• {c:3, d:4}
20.3
• 1
291
End of Chapter 21 Quiz
21.1
// many options
letters.flat(2);
// or
letters.flat().flat()
// or
letters.flat(Infinity)
21.2
Object.fromEntries(keyValueArray)
21.3
• "Alberto"
21.4
21.5
292
Introduction to TypeScript solutions
TS-01
• every
TS-02
• number
TS-03
TS-04
• 1
TS-05
293