Destructuring Arrays :
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
};
/* ------------------------------------------------------ */
// Normally you would do something like this to retrieve elements from an array:
const myArray = [1, 2, 3];
const a = myArray[0];
const b = myArray[1];
const c = myArray[2];
// But starting from ES6, you can do this in single line like:
// This means you are declaring 3 variables of type const named 'x', 'y', 'z'.
// This means you cannot later reassign x, y, or z to different values.
const [x, y, z] = myArray;
console.log(a, b, c); // Prints: 1 2 3
// It is not necessary to extract the entire array into variables. Only a part of the array can be destructured.
const [first, second] = restaurant.categories;
console.log(first, second); // Prints: Italian Pizzeria
// So what if we wanted the first and the third elements instead? We just leave a space for the second element.
let [main, , secondary] = restaurant.categories;
console.log(main, secondary); // Prints: Italian Vegeterian
// if we want to switch main and secodnary then we'd do it like this :
const temp = main;
main = secondary;
secondary = temp;
console.log(main, secondary); //Prints: Vegeterian Italian
// But now you can do just this:
// So what we are doing here is basically
// First we are creating a new array by using the [] operator containing the two elements main and secondary
// Then we are destructuring the array and storing the two elements into the swapped variables.
// We are not using let or const here because we are simple reassigning the values associated with the two variables.
[main, secondary] = [secondary, main];
console.log(main, secondary);
/* ------------------------------------------------------ */
console.log(restaurant.order(2, 0)); //Prints: [ 'Garlic Bread', 'Pizza' ]
const [starter, mainCourse] = restaurant.order(2, 0);
console.log(starter, mainCourse); // Pritns : Garlic Bread Pizza
// [nested array] :
const nested = [2, 4, [5, 6]];
let [i, , j] = nested;
console.log(i, j); // Prints: 2 [ 5, 6 ]
// destructuring the inner array
const [k, , [l, m]] = nested;
console.log(k, l, m); // Prints: 2 5 6
// [Default values]
const [p, q, r] = [8, 9];
console.log(p, q, r); // Prints: 8 9 undefined
// ### setting default values
const [p1 = 1, q1 = 1, r1 = 1] = [8, 9]; //notice how const is present here
console.log(p1, q1, r1); // Prints: 8 9 undefined
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
// we can actually do destructuring of an object rightaway and we can also set default values as well:
orderDelivery: function ({starterIndex = 1, mainIndex = 0, time = '20:00', address})
{
// we now have 4 variable names instead of an object
console.log(`Order received: ${this.starterMenu[starterIndex]}`); // Prints: Order received: Garlic Bread
},
};
// so here we are calling a function and passing an object in it
restaurant.orderDelivery({
time: '22:30',
address: 'something',
mainIndex: 2,
starterIndex: 2,
})
/* ---------------- Destructuring Objects --------------- */
// The variables names should exactly match the property names that we want to retrieve from the object
// Unlike destructuring in arrays, we do not need to specify all the properties
// and the properties can also be specified out-of-order.
// Just like arrays, this now creates 3 new variables
const { name, openingHours, categories } = restaurant;
console.log(name, openingHours, categories);
/* Prints:
Classico Italiano {thu: {…}, fri: {…}, sat: {…}}
(4)['Italian', 'Pizzeria', 'Vegetarian', 'Organic'] */
// We can also change the variable names to be different from the property names
const {name: restaurantName, openingHours: workingHours, categories: tags } = restaurant;
console.log(restaurantName, workingHours, tags);
// Using Default Values
// We can also have default values in case the property that we are trying to read does not exist on an object
// The point we are trying to make here is that:
// If a property does not exist on an object, then we would get 'undefined' as is the case when defining a variable named 'menu'
// However, if a property is not defined, and we have assigned a default value to it, the variable will take the default value instead
// as is the case with the variable 'originalMenu'
// 'starterMenu' is a valid field on the object, and we are changing it's variable name to 'starters'. Hence the default value will not be taken.
const { menu, originalMenu = [], starterMenu: starters = [] } = restaurant;
console.log(menu, originalMenu, starters); // Prints: undefined, [], ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']
/* Mutating Variables */
let a = 111;
let b = 999;
const obj = { a: 23, b: 7, c: 14 };
console.log(a); // Prints: 111
console.log(obj.a); // Prints: 23
// Now if we try to mutate the variables a and b, we will get an error because if we start a line with "{" then java script expects a code block so the trick is to wrap it in parenthesis "()"
// {a, b} = myObject;
// Hence, instead, we have to do this:
({ a, b } = obj);
console.log(a, b); // Prints: 23 7
/* nested objects */
const { fri } = openingHours;
console.log(fri); // Prints: { open: 11, close: 23 }
const { fri: {open: o, close}} = openingHours;
console.log(o, close); // Prints: 11 23
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPasta : function (ing1, ing2, ing3)
{
console.log(`Here is your pasta with ${ing1}, ${ing2}, ${ing3}.`);
},
};
/* ------------------------------------------------------ */
/* spread operator */
/* ------------------------------------------------------ */
/* ------------------------------------------------------ */
// Suppose we have an existing array, and using that we want to create a new array with some other as well.
const arr = [7, 8, 9];
const newArr = [1, 2, ...arr];
console.log(newArr); // Prints: [ 1, 2, 7, 8, 9 ]
// if we wrote const newArr = [1, 2, arr]; then we would have gotten a nested array
//basically we use spread operator when we'd otherwise write each element of the array separated by a comma.
console.log(...newArr); // Prints: 1 2 7 8 9 (this not an array but rather elements of the array)
//whereas,
// console.log(newArr); will log the 'array'
/* ------------------------------------------------------ */
const newMenu = [...restaurant.mainMenu, 'Gnocci']
console.log(newMenu); // Prints: [ 'Pizza', 'Pasta', 'Risotto', 'Gnocci' ]
// spread operator is kind of similar to destructuring as it helps us in taking elements out of an array. The big difference is that with spread operator we don't have to create new variables.
//As a consequence we can only use it in places where we'd otherwise write values separated by commas.
//copy array
const mainMenuCopy = [...restaurant.mainMenu]; //this is similar to Object.assign
// Join 2 Arrays
const menu = [...restaurant.starterMenu, ...restaurant.mainMenu];
// spread operator works on all so called iterables and not only arrays
// iterables e.g. : arrays, strings, sets, maps
// objects are not iterables
/* ------------- string and spread operator ------------- */
const str = 'Jonas';
const letters = [...str, ' ', 'S.'] // Prints: ['J', 'o', 'n', 'a', 's', ' ', 'S.']
console.log(letters);
console.log(...str); // Prints: J o n a s
/* console.log(`${...str}`)); */ // Prints: Error // this happens as template literal is not a place which expects multiple values separated by commas.
/* ------------------------------------------------------ */
/* ----------- ingredients - spread op example ---------- */
// const ingredients = [prompt('Let\'s make pasta!\nIngredient ! ?'), prompt('Ingredient 2?'), prompt('Ingredient 3?')];
// or
const ingredients = ['mushrooms', 'toilet cleaner', 'ratpoison']
console.log(ingredients); // Prints: [ 'mushrooms', 'toilet cleaner', 'ratpoison' ]
// in the old way we'd pass arguments like this :
restaurant.orderPasta(ingredients[0], ingredients[1], ingredients[2]);
// using spread operator we'd pass arguments like this :
restaurant.orderPasta(...ingredients);
// both the above lines will Print: Here is your pasta with mushrooms, toilet cleaner, ratpoison.
/* ------------------------------------------------------ */
// since es 2018 spread op also works on objects :
/* ---------------- spread op on objects ---------------- */
const newRestaurant = {cofounder: 'dude1', ...restaurant, founder: 'dude2'};
console.log(newRestaurant);
// this creates a new object
// to create a copy of an object :
const restaurantCopy = {...restaurant};
restaurantCopy.name = 'Rasoi';
console.log(restaurantCopy.name); // Prints: Rasoi
console.log(restaurant.name); // Prints: Classico Italiano
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
/* rest pattern and parameters */
/* ------------------------------------------------------ */
/* ------------------ 1.) Destructuring ----------------- */
// SPREAD, cuz on RIGHT side of =
const arr = [1, 2, ...[3, 4]];
// REST, because on LEFT side of =
const [a, b, ...others] = [1, 2, 3, 4, 5];
console.log(a, b, others); // Prints: 1 2 [ 3, 4, 5 ]
// using spread and res both :
const [pizza, , risotto, ...otherFood] = [...restaurant.mainMenu, ...restaurant.starterMenu];
console.log(pizza, risotto, otherFood); // Prints: Pizza Risotto [ 'Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad' ]
// REST must be last element, so we can't do this :
/* const [pizza, , risotto, ...otherFood, bread] = [...restaurant.mainMenu, ...restaurant.starterMenu]; */
// this will give an error as we have 'bread' afer a rest element
// aslo, there can only be one REST operator in a destructuring assignment
/* ------------------------------------------------------ */
/* ------------- rest operator with objects ------------- */
// the difference is that the remaining objects will be collected into a new object and not into a new array
const {sat, ...weekdays} = restaurant.openingHours;
console.log(weekdays); // Prints: {thu: {…}, fri: {…}}
/* ------------------------------------------------------ */
/* -------------------- 2.) Functions ------------------- */
const add = function (...numbers) {
/* console.log (numbers); */ // Prints: [ 5, 3, 7, 2 ] // which is an array
let sum = 0;
for (let i =0; i<numbers.length; i++)
sum += numbers[i];
console.log(sum);
}
add (2, 3); // Prints: 5
add(5,3,7,2); // Prints: 17
//using an array to call the above function
const x = [2,3,5,4]; // how would we call the add function with an array dawg 😭😭?? By using a spread operator 😈
add(...x); // Prints: 14
/* ------------------------------------------------------ */
restaurant.orderPizza('mushrooms', 'onion', 'olives', 'spinach'); // Prints: mushrooms, [ 'onion', 'olives', 'spinach' ]
restaurant.orderPizza('mushrooms'); // Prints: mushrooms, []
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPasta : function (ing1, ing2, ing3)
{
console.log(`Here is your pasta with ${ing1}, ${ing2}, ${ing3}.`);
},
};
/* ------------------------------------------------------ */
/* short circuiting */
/* ------------------------------------------------------ */
// Logical Operators can:
// Use ANY data type, return ANY data type, short-circuiting
/* ------------------------------------------------------ */
/* ------------------------- OR ------------------------- */
console.log('---- OR ----');
// if the first operand is truthy then it will be evaulated and the remaining operands will not even be checked.
console.log(3 || 'Jonas'); // Prints: 3
console.log('' || 'Jonas'); // Prints: Jonas // as '' is a falsey vaule
console.log(true || 0); // Prints: true
console.log(undefined || null); // Prints: null // here both are falsey values but since null comes after undefined (falsey value) so the output is null.
/* ------------------------------------------------------ */
const guests1 = restaurant.numGuests ? restaurant.numGuests : 10;
console.log(guests1); // Prints: 10 // as restaurant.numGuests doesn't exist
restaurant.numGuests = 23;
const guest2 = restaurant.numGuests || 10;
console.log(guest2); // Prints: 23
// here if instead of '23', '0' was there then we would have gotten '10' as the output. We'll learn how to fix this problem later in the chapter.
/* ------------------------- AND ------------------------ */
console.log('---- AND ----');
// In case of the && operator, it will return the first falsy value that it encounters.
// If all the values are truthy, then it will return the last value, even if the last value is truthy
console.log(0 && 'Alice'); // Prints: 0
console.log('Alice' && 'Bob'); // Prints: 'Bob'
console.log(23 && 'Alice' && true && null && 'Bob'); // Prints: null
// A practical application of this behavior is as follows:
// Suppose we are trying to call a method on the restaurant object. But we are not sure of the method exists.
// We can wrap the method inside an if-block
if (restaurant.orderPizza) {
restaurant.orderPizza('mushrooms', 'spinach');
}
// But now, with the AND operator we can do this:
// If the orderPizza property is falsy, the method is never called
restaurant.orderPizza && restaurant.orderPizza('mushrooms', 'spinach');
// But now if we add the property
restaurant.orderPizza = function () {
console.log('order pizza plzz');
};
restaurant.orderPizza && restaurant.orderPizza(); // // Prints: order pizza plzz
/* ------------------------------------------------------ */
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
/* Nullish Coalescing Operator */
/* ------------------------------------------------------ */
// if we take restaurant.numGuests = 0;
//then, JS will take it as a null value
//this is where Nullish Coalescing Operator comes in
// it was introduced in es 2020
restaurant.numGuests = 0;
const guests = restaurant.numGuests || 10;
console.log(guests); // Prints: 10
// using the Nullish Coalescing Operator
const guestsCorrect = restaurant.numGuests ?? 10;
console.log(guestsCorrect); // Prints: 0
// this happens because Nullish Coalescing Operator works with the idea of nullish values instead of falsey values
// Nullish Values : Null & Undefined (NOT 0 or '')
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
/* Logical Assignment Operators */
/* ------------------------------------------------------ */
const rest1 = {
name: 'Capri',
numGuests: 20,
};
const rest2 = {
name: 'La Piazza',
owner: 'Giovanni Rossi',
};
/* --------------- OR assignment operator --------------- */
// rest1.numGuests = rest1.numGuests || 10;
// rest2.numGuests = rest2.numGuests || 10;
// this is the same as writing :
rest1.numGuests ||= 10;
rest2.numGuests ||= 10;
console.log(rest1);
console.log(rest2);
// Similarly we can use ?? and && operators
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
/* for-of loop */
/* ------------------------------------------------------ */
const menu = [...restaurant.starterMenu, ...restaurant.mainMenu];
for (const item of menu) console.log(item); // Prints: Focaccia \n Bruschetta ...
// to get the index and the array element both we use :
for (const item of menu.entries()) console.log(item); // Prints: [ 0, 'Focaccia' ] \n [ 1, 'Bruschetta' ] ...
for (const item of menu.entries())
{
console.log(`${item[0]+1}: ${item[1]}`); // Prints: 1: Focaccia \n ...
}
// we did +1 above because in a real restaurant the list would start from a 1 and not a zero.
// we can also do it by destructuring the array :
for (const [i, el] of menu.entries())
{
console.log(`${i+1}: ${el}`); // Prints: 1: Focaccia \n ...
}
console.log(menu.entries()); // Prints: Object [Array Iterator] {}
console.log(...menu.entries()); // Prints: [ 0, 'Focaccia' ] [ 1, 'Bruschetta' ] [ 2, 'Garlic Bread' ] ...
'use strict';
const openingHours = {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
};
const restaurant = {
name: 'Classico Italiano',
// suppose we want the openingHours object inside of restaurant object as well, then, we'll have to do it like this :
openingHours: openingHours, // the problem here is that the property name on the LHS is the same the variable name on RHS from which we are getting this new object.
// This is where ES6's Enhanced Object Literals comes in handy :
openingHours, // now we have a property called hours
};
In ES6 we no longer have to create a property, and then set it to a function expression like we have always been doing.
'use strict';
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
// the above method can now be written as ;
order (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
};
Instead of just writing the property names, we can now even compute the property names :
const weekDays = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
const openingHours = {
[weekDays[3]]: {
open: 12,
close: 22,
},
[weekDays[4]]: {
open: 11,
close: 23,
},
[weekDays[5]]: {
open: 0, // Open 24 hours
close: 24,
},
};
The Optional Chaining operator ?.
is used to check if variable immediately preceding the operator exists or not. By 'exists' we mean the nullish concept and not the truthy/false concept. A value is nullish only if it is either null
or undefined
. If the variable preceding the operator is nullish, then the execution of the statement will immediately return with the value of undefined
. Else, the execution will proceed as normal.
'use strict';
// Data needed for a later exercise
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
},
order (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
// this is the trashy method of logging something if a thing exists, now imagine if we had to check whether multiple things exist or not then we'd have to use && operator which would make the code lengthy.
if (restaurant.openingHours && restaurant.openingHours.mon)
console.log(restaurant.openingHours.mon.open);
if (restaurant.openingHours.fri)
console.log(restaurant.openingHours.fri.open);
// ES2020 has a solution to this : the ? operator i.e. Optional Chaining:
//here the open propertry will be read only if restaurant.openingnHours.mon exists
console.log(restaurant.openingHours.mon?.open);
// similarly we can do for openingHours
console.log(restaurant.openingHours?.mon?.open);
// Example
const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
for (const day of days) {
const open = restaurant.openingHours[day]?.open;
console.log(`On ${day}, we open at ${open}`);
}
/* Prints:
On mon, we open at undefined
On tue, we open at undefined
On wed, we open at undefined
On thu, we open at 12
On fri, we open at 11
On sat, we open at 0
On sun, we open at undefined */
// Now suppose we dont want the undefined value here then we'll do it like this :
for (const day of days) {
const open = restaurant.openingHours[day]?.open || 'closed';
console.log(`On ${day}, we open at ${open}`);
}
/* Prints:
On mon, we open at closed
On tue, we open at closed
On wed, we open at closed
On thu, we open at 12
On fri, we open at 11
On sat, we open at closed
On sun, we open at closed */
// now the problem is that on saturday the restaurant opens at 0 but we are getting closed here. To fix this we'll use the ?? operator here instead of || (DIY)
/* ------------ methods and Optional Chaining ----------- */
console.log(restaurant.order?.(0,1) ?? 'Method does not exist')
// Prints: [ 'Focaccia', 'Pasta' ]
console.log(restaurant.orderCake?.(0,1) ?? 'Method does not exist')
// Prints: Method does not exist
// Arrays
const users = [
{name: 'Jonas',
email: 'jonas@io.io'
}
]
// Tip: when reading code basically replace '?' with 'if it exists' for convenience
console.log(users[0]?.name ?? 'Users array is empty'); // Prints: Jonas
'use strict';
// Data needed for a later exercise
const openingHours = {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
};
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours,
order (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza : function (mainIngredient, ...otherIngredients)
{
console.log(mainIngredient);
console.log(otherIngredients);
},
};
// looping over property names / keys in an object
// - Indirect Way : here we are not actually looping over the object itself but an array instead
/* ------------------- Property NAMES ------------------- */
const properties = Object.keys(openingHours);
console.log(properties); // Prints: [ 'thu', 'fri', 'sat' ] // which is an array
let openStr = `We are open on ${properties.length} days: `;
for (const day of Object.keys(openingHours))
{
console.log(day);
/* Prints:
thu
fri
sat */
}
for (const day of Object.keys(openingHours))
{
openStr += `${day}, `;
}
console.log(openStr); // Prints: We are open on 3 days: thu, fri, sat,
/* ------------------- Property Values ------------------ */
const values = Object.values(openingHours);
console.log(values);
// Prints:
/* [
{ open: 12, close: 22 },
{ open: 11, close: 23 },
{ open: 0, close: 24 }
] */
/* -------------------- Entire object ------------------- */
const entries = Object.entries(openingHours);
console.log(entries);
// Prints:
/* [
[ 'thu', { open: 12, close: 22 } ],
[ 'fri', { open: 11, close: 23 } ],
[ 'sat', { open: 0, close: 24 } ]
] */
for (const [key, {open, close}] of entries) {
console.log(`${key}: ${open}`);
}
// Prints:
/* thu: 12
fri: 11
sat: 0 */
'use strict';
// Data needed for a later exercise
const openingHours = {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
};
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours,
order(starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza: function (mainIngredient, ...otherIngredients) {
console.log(mainIngredient);
console.log(otherIngredients);
},
};
// to create a new set we write 'new Set()' inside of which we'll put an iterable such as an array :
const ordersSet = new Set(['Pasta', 'Pizza', 'Pizza', 'Risotto', 'Pasta']);
console.log(ordersSet); // Prints: Set(3) { 'Pasta', 'Pizza', 'Risotto' }
// we can see that all the duplicate values are gone
// set is also iterable
// order of elements in a set is irrelevant
// remember that string is also an iterable
console.log(new Set('Jonas')); // Prints: Set(5) { 'J', 'o', 'n', 'a', 's' }
console.log(ordersSet.size); // Prints: 3
console.log(ordersSet.has('Pizza')); // Prints: true
console.log(ordersSet.has('Bread')); // Prints: false
ordersSet.add('Garlic Bread');
ordersSet.add('Garlic Bread');
// here the 'Garlic Bread' will only be added once
ordersSet.delete('Risotto');
console.log(ordersSet); // Prints: Set(3) { 'Pasta', 'Pizza', 'Garlic Bread' }
ordersSet.clear();
/* ------------------------------------------------------ */
// how do we retrieve values out of the set ?
console.log(ordersSet[0]); // Prints: error // this doesn't work hereṇ
// there is actually no way of getting values out of a set.
// it makes sense as a set does not store duplicate values, all we need to know whether a value is in the set or not.
// if your goal is to store values in order and then retrieve it then the best use case, is to just use an array.
/* ------------------------------------------------------ */
// if we want to see what all different positions are available in a restaurant then we'll do this :
const staff = ['Waiter', 'Chef', 'Waiter', 'Manager', 'Chef', 'Waiter'];
const staffUnique = new Set(staff) // Prints: Set(3) { 'Waiter', 'Chef', 'Manager' }
console.log(staffUnique);
const staffUnique2 = [...new Set(staff)]
console.log(staffUnique2); // Prints: [ 'Waiter', 'Chef', 'Manager' ]
// this can be used to check how many unique values are there
console.log(new Set(['waiter', 'waiter', 'manager']).size); // Prints: 2
console.log(new Set('hitarth').size); // Prints: 5 // instead of 7
const rest = new Map();
rest.set('name', 'Classico Italiano');
rest.set(1, 'Firenze, Italy');
console.log(rest.set(2, 'Libson, Portugal'));
'use strict';
// Data needed for a later exercise
const openingHours = {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
};
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours,
order(starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza: function (mainIngredient, ...otherIngredients) {
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
const rest = new Map();
rest.set('name', 'Classico Italiano');
rest.set(1, 'Firenze, Italy');
console.log(rest.set(2, 'Libson, Portugal'));
rest
.set('categories', ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'])
.set('open', 11)
.set('close', 23)
.set(true, 'We are open :D')
.set(false, 'We are closed')
// in order to read data from the map we use the 'get' method
console.log(rest.get('name')); // Prints: Classico Italiano
console.log(rest.get('1')); // Prints: undefined
console.log(rest.get(1)); // Prints: Firenze, Italy
const time = 21;
console.log(rest.get(time > rest.get('open') && time < rest.get('close')));
// the statement will be resolved to give console.log(rest.get(true)); which will then further be resolved to Print: We are open :D
//has
console.log(rest.has('categories')); // Prints: true
console.log(rest.has('We are open :D')); // Prints: false
//delete
rest.delete(2); // deletes (2, 'Libson, Portugal')
console.log(rest.size); // Prints: 7
// rest.clear();
// arrays and objects as map keys :
rest.set([1,2], 'Test')
console.log(rest); // Prints: ... \n [ 1, 2 ] => 'Test'
console.log(rest.size);
console.log(rest.get([1,2])); // Prints: undefined
// here undefined is printed because the arrays in .set() and .get() are not the same arrays in heap.
// however if they are indeed the same array then it'll work
const arr = [3,4];
rest.set(arr, 'so desu ne');
console.log(rest.get(arr)); // Prints: so desu ne
'use strict';
// Data needed for a later exercise
const openingHours = {
thu: {
open: 12,
close: 22,
},
fri: {
open: 11,
close: 23,
},
sat: {
open: 0, // Open 24 hours
close: 24,
},
};
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// Data needed for first part of the section
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours,
order(starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
orderPizza: function (mainIngredient, ...otherIngredients) {
console.log(mainIngredient);
console.log(otherIngredients);
},
};
/* ------------------------------------------------------ */
const question = new Map
([
['question', 'What is the best language?'],
[1, 'C'],
[2, 'Java'],
[3, 'JavaScript'],
['correct', 3],
[true, 'correct answer !'],
[false, 'wrong answer !'],
]);
// the above structure looks similar to the structure returned by Object.entries()
console.log(Object.entries(openingHours));
// Prints:
/* [
[ 'thu', { open: 12, close: 22 } ],
[ 'fri', { open: 11, close: 23 } ],
[ 'sat', { open: 0, close: 24 } ]
] */
// so, objects can be easily converted to a map :
/* ------------ converting an object to a map ----------- */
const hoursMap = new Map (Object.entries(openingHours));
console.log(hoursMap);
// Prints:
/* Map(3) {
'thu' => { open: 12, close: 22 },
'fri' => { open: 11, close: 23 },
'sat' => { open: 0, close: 24 }
} */
/* ------------------------------------------------------ */
/* ---------------------- iteration --------------------- */
//Quiz App
console.log(question.get('question'));
for (const [key, value] of question)
{
if(typeof key === 'number')
console.log(`${key}: ${value}`);
}
// const answer = Number(prompt('Your answer'))
const answer =3;
console.log((question.get(answer === question.get('correct'))));
/* ------------------------------------------------------ */
/* ---------------- convert map to array ---------------- */
console.log(...question);
// Prints:
/* [ 'question', 'What is the best language?' ] [ 1, 'C' ] [ 2, 'Java' ] [ 3, 'JavaScript' ] [ 'correct', 3 ] [ true, 'correct answer !' ] [ false, 'wrong answer !' ] */
/* ------------------------------------------------------ */
/* ------------------- other operators ------------------ */
console.log(question.entries());
console.log(question.keys());
console.log(question.values());
console.log(question.keys()); // Prints: [Map Iterator] { 'question', 1, 2, 3, 'correct', true, false }
console.log(...question.keys()); // Prints: question 1 2 3 correct true false
indexOf()
& slice()
:const airline = 'TAP Air Portugal';
const plane = 'A320';
/* ----------------------- length ----------------------- */
console.log(plane[2]); // Prints: 1
console.log(airline.length); // Prints: 16
console.log('B737'.length); // Prints: 4
console.log(airline.indexOf('T')); // Prints: 0
// Search from the end of the string
console.log(airline.lastIndexOf('r')); // Prints: 10
// Search for the occurrence of the word
console.log(airline.indexOf('portugal')); // Prints: -1. Because it is case-sensitive and string contains 'Portugal' not 'portugal'
// Slice the string starting from index 4 to the end of the string
console.log(airline.slice(4)); // Prints: 'Air Portugal'
// Slice the string from index 4 included, index 7 excluded
console.log(airline.slice(4, 7)); // Prints: 'Air'
// Start from the index 0, right up to the first occurrence of the ' '
console.log(airline.slice(0, airline.indexOf(' '))); // Prints: 'TAP ' // Note that there is a space.
// Start from the index AFTER the last index of ' ', right up to the end of the string
console.log(airline.slice(airline.lastIndexOf(' ') + 1)); // Prints: 'Portugal'
// Start from the end of the string. Print the first two characters
console.log(airline.slice(-2)); // Prints: 'al'
// Start from the index 1 print up to the index before the last one
console.log(airline.slice(1, -1)); // Prints: 'AP Air Portuga'
// Whenever we call a method on a string JS behind the scenes will convert the string primitive to a string object and it's on that object where methods are called. This process is called Boxing.
// JS internally changes the type of string by boxing and unboxing as required
console.log(typeof 'JavaScript Strings'); // Prints: string
console.log(typeof new String('JavaScript Strings')); // Prints: object. Warning: Primitive type object wrapper used
console.log(typeof String('JavaScript Strings')); // Prints: string
toLowerCase
, toUpperCase
, includes
, replace
, replaceAll
, includes
, startsWith
, endsWith
:"use strict";
const airline = "TAP Air Portugal";
console.log(airline.toLowerCase()); // → tap air portugal
console.log(airline.toUpperCase()); // → TAP AIR PORTUGAL
// Fix capitalization in name
const passenger = "jOnAS";
const passengerLower = passenger.toLowerCase();
const passengerCorrect =
passengerLower[0].toUpperCase() + passengerLower.slice(1);
console.log(passengerCorrect); // → Jonas
// Check email
const email = "hello@jonas.io";
const loginEmail = " Hello@Jonas.IO \n";
const normalizedEmail = loginEmail.toLowerCase().trim();
console.log(normalizedEmail === email); // → true
// Replacing : .replace only replaces the first appearance of the character/word
const priceGB = "288,98£";
const priceUS = priceGB.replace("£", "$").replace(",", ".");
console.log(priceUS); // → 288.98$
const announcement =
"All passengers come to boarding door 23. Boarding door 23!";
console.log(announcement.replaceAll("door", "gate"));
// → All passengers come to boarding gate 23. Boarding gate 23!
// Booleans
const plane = "Airbus A320neo";
console.log(plane.includes("A320")); // → true
console.log(plane.startsWith("Air")); // → true
if (plane.startsWith("Airbus") && plane.endsWith("neo")) {
console.log("Part of the NEW Airbus family");
} // → Part of the NEW Airbus family
// Practice exercise
const checkBaggage = function (items) {
const baggage = items.toLowerCase();
if (baggage.includes("knife") || baggage.includes("gun")) {
console.log("You are NOT allowed on board!");
} else {
console.log("Welcome abroad!");
}
};
checkBaggage("I have a laptop, some Food and a pocket knife");
// → You are NOT allowed on board!
checkBaggage("Socks and camera");
// → Welcome abroad!
checkBaggage("Got some snacks and a gun for protection");
// → You are NOT allowed on board!
"use strict";
console.log("a+very+nice+string".split("+"));
// → (4) ['a', 'very', 'nice', 'string']
// Split and Join
const [firstName, lastName] = "Pavel Georgiev".split(" ");
const newName = ["Mr.", firstName, lastName.toUpperCase()].join(" ");
console.log(newName); // → Mr. Pavel GEORGIEV
const capitalizeName = function (name) {
const names = name.split(" ");
const namesUpper = [];
for (const n of names) {
namesUpper.push(n.replace(n[0], n[0].toUpperCase()));
}
console.log(namesUpper.join(" "));
};
capitalizeName("jessica ann smith davis"); // → Jessica Ann Smith Davis
capitalizeName("pavel georgiev"); // → Pavel Georgiev
// Padding
const message = "Go to gate 23!";
console.log(message.padStart(25, "+")); // → +++++++++++Go to gate 23!
console.log(message.padEnd(25, "+")); // → Go to gate 23!+++++++++++
const maskCreditCard = function (number) {
const str = number + ""; // to convert the number to a string
const last = str.slice(-4);
return last.padStart(str.length, "*");
};
console.log(maskCreditCard(32415216)); // → ****5216
console.log(maskCreditCard("62416278")); // → ****6278
// Repeat
const message2 = "foo ";
console.log(message2.repeat(5)); // → foo foo foo foo foo
const planesInLine = function (n) {
console.log(`There are ${n} planes in line ${"🛩".repeat(n)}`);
};
planesInLine(5); // → There are 5 planes in line 🛩🛩🛩🛩🛩
planesInLine(3); // → There are 3 planes in line 🛩🛩🛩
planesInLine(12); // → There are 12 planes in line 🛩🛩🛩🛩🛩🛩🛩🛩🛩🛩🛩🛩
'use strict';
const flights =
'_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
/* ------------------------------------------------------ */
// 🔴 Delayed Departure from FAO to TXL (11h25)
// Arrival from BRU to FAO (11h45)
// 🔴 Delayed Arrival from HEL to FAO (12h05)
// Departure from FAO to LIS (12h30)
/* ------------------------------------------------------ */
for ( const flight of flights.split('+'))
{
const [type, from, to, time] = flight.split(';');
const output = `${type.startsWith('_Delayed') ? '🔴' : ''}${type.replaceAll('_', ' ')} from ${from.slice(0, 3).toUpperCase()} to ${to.slice(0, 3).toUpperCase()} (${time.replace(':', 'h')})`.padStart(44);
console.log(output);
}