Javascript

Data structures, Moden operators and strings

mossybeach 2024. 4. 23. 17:49

Destructuring

we can destructure an array or object by reassigning their values using a function or by creating a new array.

 

 

ways of destructuring

  • destructuring
const arr = [2, 3, 4];
const [x, y, z] = arr;
console.log(x, y, z);
 

 

we can also switch variables

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'], 
}

 

let [main, , secondary] = restaurant.categories;
console.log(main, secondary);
//Italian, Vegetarian

 

[main, secondary] = [secondary, main];
console.log(main, secondary);
// Vegetarian, Italian

 

we can also use a function to capture the variable we want before assigning them to a new value

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]];
  },

 

const [starter, mainCourse] = restaurant.order(2, 0);
console.log(starter, mainCourse);
//Garlic bread, Pizza

 

  • nested destructuring
const nested = [2, 4, [5, 6]]; //array inside array = nested
const [i, , [j, k]] = nested;
console.log(i, j, k); //we need to destructure within the destructure 
//2,5,6
  • default values
const [p = 1, q = 1, r = 1] = [8, 9];
console.log(p, q, r);
1,1,1

 


Destructuring objects

destructuring objects is extremely useful when it comes to using API as it comes in obj form.

 

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'],
}

 

  • new variables
const { name, openingHours, categories } = restaurant;
//creates 3 brandnew variables (name, opening hours, categories)
console.log(name, openingHours, categories);
// Classico Italiano {thu: {…}, fri: {…}, sat: {…}}fri: {open: 11, close: 23}sat: {open: 0, close: 24}thu: {open: 12, close: 22}[[Prototype]]: Object (4) ['Italian', 'Pizzeria', 'Vegetarian', 'Organic']

 

we can also assign new names to the new variables by doing this

const {
  name: restaurantName,
  openingHours: hours,
  categories: tags,
} = restaurant;

 

  • default values 

  It's useful to set defaults if we are retrieving data from an external source and we don't know what it looks like instead of having 'hard data' where we have it in the code intead of using a json or api.

const { menu = [], starterMenu: starters = [] } = restaurant;

console.log(menu, starters);// [] (4) ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']
 

 

  • Mutating variables (similar to switching variables in array)
let a = 111;
let b = 999;
const obj = { a: 23, b: 7, c: 14 };

({ a, b } = obj); //we need to wrap it into parenthesis since it cant start with curly braces
console.log(a, b);
//23, 7

 

We should always wrap objects in parenthesis when declaring them to avoid error

  • nested objects
  openingHours: {
    thu: {
      open: 12,
      close: 22,
    },
    fri: {
      open: 11,
      close: 23,
    },
    sat: {
      open: 0, // Open 24 hours
      close: 24,
    },
  }

 

since there's an object within an object, we use two curlies to depict this in code

const {
  fri: { open: o, close: c },
} = openingHours;
console.log(o, c);
//11,23

 


full recap of what we learned so far

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]];
  },
 
  orderDelivery: function ({ starterIndex, mainIndex, time, address }) {
    console.log(
      `  order received ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]}, will be delivered to ${address} at ${time}`
    );
  },
};

 

restaurant.orderDelivery({
  time: '22:30',
  address: 'Via del Sole, 21',
  mainIndex: 2,
  starterIndex: 2,
});
 
// order received Garlic Bread and Risotto, will be delivered to Via del Sole, 21 at 22:30

The Spread Operator (...)

We can use the spread operator to unpack an array.

const arr = [7, 8, 9]; //array literal
const newArr = [1, 2, ...arr];
console.log(...newArr); //1 2 7 8 9

 

we can use spread operator to create a copy of an array and add to it

example 1:

const mainMenuCopy = [...restaurant.mainMenu]; 
// [['Pizza', 'Pasta', 'Risotto']

 

 

example 2:

const newMenu = [...restaurant.mainMenu, 'gnocci'];
console.log(newMenu);// ['Pizza', 'Pasta', 'Risotto', 'gnocci']

 

example 3:

const menu = [...restaurant.mainMenu, ...restaurant.starterMenu];
console.log(menu); // ['Pizza', 'Pasta', 'Risotto', 'Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']

 


using spread operator in a function

  orderPasta: function (ing1, ing2, ing3) {
    console.log(
      `here is your delicious pasta with ${ing1}, ${ing2} and ${ing3}`
    );

const ingredients = [
  prompt(`let's make pasta! ingredient 1?`),
  prompt(`ingredient 2?`),
  prompt(` ingredient 3?`),
];
 
console.log(ingredients); // ['cheese', 'pesto', 'tomato']
 
restaurant.orderPasta(...ingredients);
//here is your delicious pasta with cheese, pesto and tomato
 
 

spread operator works on all iterables: things like arrays, strings, maps and sets, not objects!!)

 

spread operator used on string:

const str = 'Roxy';
const letters = [...str, '', 's'];
console.log(letters); 
//['R', 'o', 'x', 'y', '', 's']

after 2016, we can also use spread operator for objects


const newRestaurant = { foundedIn: 1988, ...restaurant, founder: `Antonio` };
console.log(newRestaurant);
 
//{foundedIn: 1988, name: 'Classico Italiano', location: 'Via Angelo Tavanti 23, Firenze, Italy', categories: Array(4), starterMenu: Array(4), …}
categories

(4) ['Italian', 'Pizzeria', 'Vegetarian', 'Organic']
foundedIn

1988
founder

"Antonio"
location

"Via Angelo Tavanti 23, Firenze, Italy"
mainMenu

(3) ['Pizza', 'Pasta', 'Risotto']
name

"Classico Italiano"
openingHours

{thu: {…}, fri: {…}, sat: {…}}
order

ƒ (starterIndex, mainIndex)
orderDelivery

ƒ ({ starterIndex, mainIndex, time, address })
orderPasta

ƒ (ing1, ing2, ing3)
starterMenu

(4) ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']

 


Rest Pattern and Parameters

is the opposite of a spread operator where it collects items and pack them into an array

 

spread is on the right side of the assignment operator HOWEVER we can also use it on the left side!!

 

spread:

const arr = [1, 2, ...[3.4]];

 

rest:

const [a, b, ...others] = [1, 2, 3, 4, 5];
console.log(a, b, others);
//1 2 (3) [3, 4, 5]
 

it collects the element unused and puts them into others

 

example 2:

const [pizza, , risotto, ...otherFood] = [
  ...restaurant.mainMenu,
  ...restaurant.starterMenu,
];
console.log(pizza, risotto, otherFood);
// Pizza Risotto (4) ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'] it skips pasta as it is not included

 

the rest element must be the last element and there can be only one!!!

 

example 3: using rest patterns for objects

const { sat, ...weekDays } = restaurant.openingHours;
console.log(weekDays);
//{thu: {…}, fri: {…}}

 

example 4: using functions (REST ARGUMENT)

 

const add = function (...numbers = this is called a rest argument) {
  let sum = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
    console.log(sum);
  }
};
add(2, 3);
add(5, 3, 7, 2);
add(8, 2, 3, 2, 1, 4);

const x = [23, 5, 7];
add(...x);

 

 

 


short circuiting (&& and ||)

  • logical operators can use any data type
  • they can return any data type

 

  • they do short circuiting / short circuit evaluation: if the first value is a truthy value, it will immediately return the truthy value but will return the last value if all of them are falsies

example 1:

console.log(3 || 'roxy');
// 3 

 

since it immediately returns the truthy value, it will not even consider nor read the other option 

 

example 2:

console.log('' || 'roxy'); //roxy
console.log(true || 0); //true
console.log(undefined || null); //null. even though null is a falsy

 

example 3:

console.log(undefined || 0 || '' || 'hello' || 23 || null);
//hello because its the first truthy value

 


|| short circuiting

 

instead of using a ternary operator for something like this

const guest1 = restaurant.numGuests ? restaurant.numGuests : 10;
console.log(guest1);
//10

= if numGuest exists show numGuest, if not show the default value of 10

 

we can also do this using short circuits for if, else statements

const guest2 = restaurant.numGuests || 10;
console.log(guest2);
//10

 

but both of these will not work if restaurant.numGuest will be 0 as 0 is a falsy value so it will go to the truthy value which is the default 10


&& short circuiting

works the exact oposite of the or value (||)

so it will focus on the first falsy value or the last value if all of them are truthy and will not focus on the next/ truthy value

 

example 1:

console.log(0 && 'Jonas'); //0
console.log(7 && 'Jonas'); //Jonas
console.log('hello' && 23 && null && 'jonas'); //null

 


using the && short circuit in place of an if statement

 

instead of 

if (restaurant.orderPizza) {
  restaurant.orderPizza('mushroom', 'cheese');
}

 

we can use

restaurant.orderPizza && restaurant.orderPizza('mushroom', 'cheese');

 

but this doesn't mean we need to replace all if, else statements with these!!! just use accordingly depending on the situation!!

 


 The Nullish Coalescing Operator(??)

similar to the And or Or operator ( && , ||), the nullish operator works with the concept of nullish values instead of falsy values

 

Nullish values are null and undefined ( so it can handle 0 or ' ')

 

therefore

restaurant.numGuests = 0;
const guestCorrect = restaurant.numGuests ?? 10;
console.log(guestCorrect); //0

 

the 0 will show up instead of going to the default value of 10 as the nullish operator recognizes 0 as a value.

 


Recap and simplifying operators (||, &&, ??)

  • Or operator (||)
rest1.numGuests = rest1.numGuests || 10;
rest2.numGuests = rest2.numGuests || 10;
rest1.numGuests ||= 10;
rest2.numGuests ||= 10; //kinda like +=

 

 

  • And operator (&&)
rest2.owner = rest2.owner && 'anonymous';
// since the first value is truth it pushes out the 'falsy value'
rest2.owner = rest2.owner && 'anonymous';

rest1.owner &&= 'anonymous';
rest2.owner &&= 'anonymous';
console.log(rest1.owner);
console.log(rest2.owner);

 

  • Nullish operator (??)
rest1.numGuests ??= 10;
rest2.numGuests ??= 10;

 

 


 

For Of Loop 

 

instead of setting different parameters like the for loop we can simply assign a vairable we want to use directly

const menu = [...restaurant.mainMenu, ...restaurant.starterMenu];
for (const item of menu) console.log(item);
//Pizza
Pasta
Risotto
 Focaccia
Bruschetta
 Garlic Bread
 Caprese Salad

 

there is also something called entries which we will learn later but to simply put it, its to create a numbered list

for (const item of menu.entries()) {
  console.log(`${item[0] + 1}: ${item[1]}`);
}
//1: Pizza
 2: Pasta
 3: Risotto
 4: Focaccia
5: Bruschetta
6: Garlic Bread
 7: Caprese Salad

 

however we can simplify this further by destructuring the above

for (const [i, el] of menu.entries()) {
  console.log(`${i + 1}: ${el}`);
}

 

further excercises

 

//the for of loop
//8.1

let pageSum = 0;
for (let book of books) {
  pageSum += book.pages;
  console.log(pageSum);
}

//8.2
let allAuthors = [];

for (const book of books) {
  if (typeof book.author === `string`) {
    allAuthors.push(book.author);
  } else {
    for (const author of book.author) {
      allAuthors.push(author);
    }
  }
}
console.log(allAuthors);

//8.3
for (const [i, name] of allAuthors.entries()) {
  console.log(` ${i + 1}: ${name} `);
}

Enhanced object literals 

thanks to ES6 updates we can simplify some of the code we write through using enhance object literals: writing literally using obj literal syntax

  • if we have a seperate object and we want to insert it into another we can just write the name into the object

example: 

 

const hours = {
  [weekDays[3]]: {
    open: 12,
    close: 22,
  },
  [weekDays[4]]: {
    open: 11,
    close: 23,
  },
  [weekDays[2 + 3]]: {
    open: 0, // Open 24 hours
    close: 24,
  },
};

 

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'],
 
hours,  // like this!!
}

 

  • we can also simplify functions in an object 

instead of writing a key: name of function and value: function, we can directly create a function like this

  order(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
  },

 

  • we can also reference other arrays into an object

example: 

const weekDays = ['mon', 'tues', 'wed', 'thurs', 'fri', 'sat', 'sun'];
 
const hours = {
  [weekDays[3]]: {
    open: 12,
    close: 22,
  },
  [weekDays[4]]: {
    open: 11,
    close: 23,
  },
  [weekDays[2 + 3]]: {
    open: 0, // Open 24 hours
    close: 24,
  },
};

Optional Chaining (?.)

we can use optional chaining to see if a certain variable exists!

 

  • optional chaining in an object
console.log(restaurant.hours?.mon?.open);

 

the ?. works as a chain gate, it will only move onto the next element if the variable exists. if not it will show up as undefined or as the default value set 

const days = ['mon', 'tues', 'wed', 'thurs', 'fri', 'sat', 'sun'];
for (const day of days) {
  console.log(day);
  const open = restaurant.hours[day]?.open ?? 'closed';
  console.log(`on ${day}, we open at ${open}`);
}

 

  • optional chaining in methods
console.log(restaurant.order?.(0, 1) ?? 'method does not exist');
console.log(restaurant.orderRistto?.(0, 1) ?? 'method does not exist');

 

  • optional chaining in arrays
//arrays
const users = [{ name: 'jonas' }, { email: `hello@jonas.io` }];
console.log(users[0]?.name ?? `user array empty`);

 

optional chaining and the nullish operator was made to use side by side like the case above

 


Looping Objects: Object Keys, Values, and Entries

As we have learned before in objects there are keys and values. And we can use these to retrieve information.

const hours = {
  [weekDays[3]]: {
    open: 12,
    close: 22,
  },
  [weekDays[4]]: {
    open: 11,
    close: 23,
  },
  [weekDays[5]]: {
    open: 0, // Open 24 hours
    close: 24,
  },
};
  • keys
const properties = Object.keys(hours);
console.log(properties);
let openStr = `we are open for ${properties.length} days`;
for (const day of Object.keys(hours)) {
  openStr += `${day},`;
}
console.log(openStr);
// we are open for 3 days fri,sat, sun

 

  • values
const values = Object.values(hours);
console.log(values);
//0: {open: 12, close: 22}
1: {open: 11, close: 23}
2: {open: 0, close: 24}
 

 

  • entries
const entries = Object.entries(hours);
// console.log(entries);
//

 

 

combined togther:

for (const [key, { open, close }] of entries) {
  console.log(`on ${key} we open at ${open} and close at ${close}`);
}
on thurs we open at 12 and close at 22
script.js:78 on fri we open at 11 and close at 23
script.js:78 on sat we open at 0 and close at 24

'Javascript' 카테고리의 다른 글

JavaScript: Behind the scenes  (0) 2024.04.04
DOM and Events Fundamentals  (0) 2024.04.03
JavaScript Fundamental part 2  (0) 2024.01.29
JavaScript fundamental notes 1  (0) 2024.01.23