Data structures are the basis of JavaScript, without them we couldn't really manipulate everything, and despite variables being the most basic feature, data structures use these variables to actually achieve anything so, I'm going to talk everything about Data Structures in the next few days.
As always, we being our code with:
"use scrict";
Destructuring arrays
This is an ES6 features, and it is a way of unpacking values from an array or an object into separate values. We break a comples data structure into a smaller data structure like a variable. We retrieve elements from an array to store them into variables.
const restaurant = {
name: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Lasagna", "Pesto Pasta", "Four Cheese Spaghetti"],
mainMenu: ["Pizza", "Pasta", "Risotto"],
};
const array1 = [2, 3, 4];
const a = array1[0];
const b = array1[1];
const c = array1[2];
console.log(a, b, c); // Output: 2, 3, 4
But we can also declare them at the same time:
const [x, y, z] = array1; // 1
// 2
console.log(x, y, z); // Output: 2, 3, 4
1. x becomes the first element of the array, y the second and z the third.
2.Whenever JS sees [] on the left side of the equal sign, it knows that it should do destructuring.
We don't need to take all of the elements from the array, we can do only some:
const [first, second] = restaurant.categories; // 3
console.log(first, second); // Output: Italian Pizzeria
3.We use first and second as keywords to only take the first two, but we can actually use any word we want.
This means that we can actually take the first and the third by leaving a blank space, using any kind of word.
const [one, , two] = restaurant.categories;
console.log(one, two); // Output: Italian Vegetarian
Let's say we want to switch the categories in the third property of the array:
let [primary, , secondary] = restaurant.categories;
[primary, , secondary] = [secondary, , primary]; // 4
console.log(primary, secondary); // Output: Vegetarian Italian
4.We don't use const or let because we are not storing them, we are just switching them.
We can make a function return an array and then immediately destructure the result into different variables. This allows us to return multiple values from a function.
const restaurant = {
name: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Risotto"],
order: function (starterIndex, mainIndex) {
// 5
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
};
console.log(restaurant.order(1, 0)); // Output: ["Garlic Bread", "Pizza"]
5.This function will accept two parameters, one for the starter menu and the other for the main menu.
But we haven't destructured that, we just called the elements, to destructure them we:
This is how we receive 2 values from a function
const [starterCourse, mainCourse] = restaurant.order(1, 0);
console.log([starterCourse, mainCourse]); // Output: [ 'Garlic Bread', 'Pizza' ]
console.log(starterCourse); // Output: Garlic Bread
Now, let's talk nested arrays and destructuring them
Take the next array as an example:
const nestedArray = [2, 3, [4, 5]];
const [first, , second] = nestedArray;
console.log(first, second); // Output: 2 [4, 5]
And if we want to take each element and store it into a variable, including the two elements inside the nested array, we would need to do as follows:
const nestedArray = [2, 3, [4, 5]];
const [first, second, [third, fourth]] = nestedArray;
console.log(first, second, third, fourth); // Output: 2 3 4 5
Another feature of destructuring is setting default values for the values when we are extracting them. This is useful in case we don't know the length of the array (which happens very often irl)
const [d = "no element", e = "no element", f = "no element"] = [8, 9]; // 5
console.log(d, e, f); //Output: 8 9 no element
5.Let's pretend we don't know the length of the array
When we call 3 elements from an array with only two elements, we'll receive the existing position values, and those that don't exist, we'll get the default value.
Destructuring objects
Let's take the example from the italian restaurant because I don't feel like coming up with another example:
const restaurant = {
name: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
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]];
},
};
To destructure objects we use curly braces {}, all we have to do is provide the variable names that match exactly the property names that we want to retrieve from the object.
Remember, unlike in arrays, in objects the order of the elements doesn't matter so we don't need to skip elements.
const { name, openingHours, categories } = restaurant;
// This creates three new variables based on the restaurant object.
console.log(name, openingHours, categories);
Output:
Ristorante di Paolo {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 }
} [ 'Italian', 'Pizzeria', 'Vegetarian' ]
But what if we want the variable names to be diffferent from the property names? We still need to reference the properties, check it out:
const {
name: restaurantName,
openingHours: Hours,
categories: tags,
} = restaurant;
console.log(restaurantName, Hours, tags);
This is very useful when we are dealing with a third party data.
We can also set default values for properties that do not exist in the object.
const { menu = [], starterMenu: starters = [] } = restaurant; // 6.
console.log(menu, starters); // Output: [] [ 'Salad', 'Garlic Bread', 'Cheese' ]
6.We set the default value to an empty array in case the property doesn't exist
To mutate variables while destructuring objects:
let a = 111;
let b = 999;
const obj = { a: 23, b: 7, c: 14 };
({ a, b } = obj); // 7.
console.log(a, b, { a, b }); // Output: 23 7 { a: 23, b: 7} // 8.
7.We are rewriting the values of a and b with the values from the object.
Now, if we really want to destructure an object, we have to take it to the next level. To deal with nested objects we need to do the following: 9.We created these 3 variables above, just copying them to use them. We want two variables, one called open and one called close. 10.We know that [fri] is an object, so we can destructure it using the Many times in JS we have several functions with several parameters, and it can be hard to know the order of parameters so instead of defining the parameters manually, we can pass an object into the function as an argument and the function will immediately destructure that object. We passed an object, not four variables, this is extremely important. The function received the object with the exact same name of the parameters as the arguments and thus, was able to destructure it and pass in the values. And notice that the order of the properties doesn't need to match. We can also pass default values to said function in case the client doesn't specify the values. We can use it to expand into all its elemeents. Like unpacking all the elements at once. 11.We want to create a new array with new elements. Using the spread operator: The spread operator takes all the values of an array and writes them individually as if we did it just like in the first way. We can use the spread operator whenever we write multiple an array literal or when we pass arguments into functions. Using the old restaurant object we can go deeper into the spread operator functionalities: The difference between the spread operator and destructuring arrays is that the spread operator takes all the elements from the array, and it doesn't create new variables, so we can only use it in situations when we would write values separated by commas. Creating shallow copies of arrays Merge two arrays together Note to self: Iterables are arrays, string, maps and sets, but not objects. 14.We unpacked the string and built an array from each letter: [ 'E', 'r', 'i', 'c', ' ', 'S.' ] We can also build functions and use the spread operator to modify them, let's use the restaurant example for that: The spread operator also works with objects even though they are not iterable, and it works as follows: 15.we are creating a copy so we can modify this one without changing the original. There's still a lot to learn about data structures, I'm barely scratching the surface but, I'm just getting warm but this post was already too long. Hopefully you found it useful, I hope I can post again about this topic tonight.
const restaurant = {
restName: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
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]];
},
};
const { restName, openingHours, categories } = restaurant; // 9
const {
fri: { open, close },
} = openingHours; // 10
console.log(open, close); // Output: 11 23 (as variables)
const restaurant = {
restName: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
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]];
},
orderDelivery: function ({ starterIndex, mainIndex, time, address }) {
console.log(
`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`
);
},
};
const { restName, openingHours, categories } = restaurant;
const {
fri: { open, close },
} = openingHours;
console.log(open, close);
restaurant.orderDelivery({
time: "22:30",
address: "Elm street 8",
mainIndex: 2,
starterIndex: 1,
});
orderDelivery: function ({ starterIndex = 1, mainIndex =1, time = 20:00, address = "Pick up at store" })
Spread operator
const arr = [7, 8, 9]; // 11
const badNewArr = [1, 2, arr[0], arr[1], arr[2]]; // 12
12.But this manual method is just unefficient.const newArr = [1, 2, ...arr];
console.log(newArr); // Output: [ 1, 2, 7, 8, 9 ] But in a cleaner way
const restaurant = {
restName: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
};
const newMainMenu = [...restaurant.mainMenu, "Gnocci"]; // `13
console.log(newMainMenu); // Ouput: [ 'Pizza', 'Pasta', 'Lasagna', 'Gnocci' ]
13.We are creating a new array, not manipulating the original array.
Use Cases:
const mainMenuCopy = [restaurant.mainMenu];
const fullMenu = [...restaurant.mainMenu, ...restaurant.starterMenu];
console.log(fullMenu); // Output: [ 'Pizza', 'Pasta', 'Lasagna', 'Salad', 'Garlic Bread', 'Cheese' ]
const str = "Eric";
const letters = [...str, " ", "S."];
console.log(letters); // 14
const restaurant = {
restName: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
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]];
},
orderDelivery: function ({ starterIndex, mainIndex, time, address }) {
console.log(
`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`
);
},
orderPasta: function (ing1, ing2, ing3) {
console.log(`Here's your pasta with ${ing2}, ${ing2} and ${ing3}`);
},
};
const ingredients = [
prompt("Let's make pasta! Ingredient 1?"),
prompt("Let's make pasta! Ingredient 2?"),
prompt("Let's make pasta! Ingredient 3?"),
];
console.log(ingredients);
restaurant.orderPasta(...ingredients);
const restaurant = {
restName: "Ristorante di Paolo",
location: "Chipilo, Mexico",
categories: ["Italian", "Pizzeria", "Vegetarian"],
starterMenu: ["Salad", "Garlic Bread", "Cheese"],
mainMenu: ["Pizza", "Pasta", "Lasagna"],
};
const newRestaurant = {
...restaurant,
founder: "Paolo DiPaolini",
employees: 2,
employeesNames: ["Luca", "Marlena"],
}; // We added a lot of properties to the object
console.log(newRestaurant); // Output:
const restaurantCopy = { ...restaurant }; // 15