Hiểu Rõ Rest Pattern & Rest Parameters trong JavaScript
Chào các em, hôm nay thầy chia sẻ một phần rất hay ho trong JavaScript – đó là Rest Pattern và Rest Parameters. Nhìn thì giống Spread Operator nhưng “bản chất thì ngược đời” 😄
Rest và Spread có gì giống – khác?
Các em còn nhớ Spread Operator (...
) chứ?
- Dùng để tách mảng thành từng phần tử riêng lẻ.
- Hay truyền nhiều giá trị vào hàm cùng lúc.
Ví dụ:
const arr = [1, 2, 3];
console.log(...arr); // => 1 2 3
Nhưng giờ đến lượt Rest Pattern (...
) xuất hiện – cũng ba chấm, nhưng làm điều ngược lại: gom các phần tử lại thành mảng!
- Spread: Tách ra.
- Rest: Gom lại.
Rest Pattern trong Destructuring
Trường hợp mảng
Giả sử mình có mảng sau:
const arr = [2, 3, 4, 5];
Thầy muốn lấy hai phần tử đầu ra riêng, phần còn lại gom vào một biến:
const [a, b, ...others] = arr;
console.log(a); // 2
console.log(b); // 3
console.log(others); // [4, 5]
📌 Lưu ý:
- Rest Pattern chỉ dùng được ở cuối khi destructuring!
- Không thể viết
[...rest, last] = arr
nhé, vì JS sẽ không biết “gom tới đâu” ❌. - Chỉ được 1 rest trong mỗi destructuring.
Destructuring mảng thực tế hơn tí
Ví dụ với một menu:
const menu = ["Pizza", "Pasta", "Risotto", "Burger", "Salad"];
const [pizza, , risotto, ...otherFood] = menu;
console.log(pizza); // Pizza
console.log(risotto); // Risotto
console.log(otherFood); // ['Burger', 'Salad']
📌 Lưu ý tiếp:
- Phần tử bị bỏ qua (ở đây là
'Pasta'
) không nằm trong mảng rest. - Rest pattern sẽ gom từ phần tử sau cùng có tên biến trở đi.
Với Object cũng tương tự
const openingHours = {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 },
};
const { sat, ...weekdays } = openingHours;
console.log(sat);
// { open: 0, close: 24 }
console.log(weekdays);
// { thu: {...}, fri: {...} }
Ở đây, sat
được lấy riêng, còn weekdays
gom phần còn lại vào object mới.
Rest Parameters trong hàm
Chuyển qua phần hàm – khi các em muốn viết một hàm nhận số lượng đối số tùy ý, thì dùng rest parameters là lựa chọn cực hợp lý.
Ví dụ hàm cộng:
function add(...numbers) {
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
console.log(sum);
}
add(2, 3); // 5
add(5, 3, 7, 2); // 17
📌 numbers
trong ví dụ trên là một mảng chứa tất cả đối số được truyền vào.
Kết hợp với Spread
const x = [23, 5, 7];
add(...x); // cũng ra 35
Ở đây:
...x
(spread) giúp “bung” mảng thành từng giá trị rời.- Sau đó,
...numbers
(rest) gom lại thành mảng trong hàm.
🔥 Một ví dụ điển hình cho thấy Spread và Rest làm việc “trái dấu” với nhau.
Hàm thực tế: Order Pizza
Thầy viết một hàm order pizza có 1 nguyên liệu chính, còn lại là topping tùy thích:
const orderPizza = function (mainIngredient, ...otherIngredients) {
console.log(mainIngredient);
console.log(otherIngredients);
};
orderPizza("Mushrooms", "Onion", "Olives", "Spinach");
Kết quả:
Mushrooms
['Onion', 'Olives', 'Spinach']
Nếu chỉ truyền 1 nguyên liệu:
orderPizza("Mushrooms");
Thì otherIngredients
sẽ là một mảng rỗng []
.
Tóm tắt nhanh
- Rest Pattern (
...
) dùng để gom phần còn lại:- Dùng trong destructuring (array hoặc object).
- Chỉ được dùng ở cuối, chỉ có một lần duy nhất.
- Rest Parameters:
- Dùng trong định nghĩa hàm.
- Gom tất cả các tham số còn lại thành mảng.
- Spread: Tách giá trị ra.
- Rest: Gom giá trị lại.
- Chúng giống nhau về cú pháp (
...
), nhưng ngược nhau về công dụng.
Bài tập thực hành
1. Destructure keywords
từ sách đầu tiên
Destructure thuộc tính keywords
(mảng) của sách đầu tiên từ mảng books
thành các biến mainKeyword
và rest
.
mainKeyword
sẽ chứa từ khóa đầu tiên.rest
sẽ chứa các từ khóa còn lại (mảng).
const books = [
{ title: "Book 1", keywords: ["JavaScript", "Programming", "Web"] },
// ...other books
];
// {...}
Hiển thị lời giải mẫu
const [mainKeyword, ...rest] = books[0].keywords;
console.log(mainKeyword); // JavaScript
console.log(rest); // ['Programming', 'Web']
2. Destructure sách thứ hai
Destructure sách thứ hai từ mảng books
thành biến bookPublisher
.
bookPublisher
sẽ chứa giá trị của thuộc tínhpublisher
.- Các thuộc tính còn lại sẽ được gán vào biến
restOfTheBook
.
const books = [
// ...other books
{ title: "Book 2", publisher: "O'Reilly", year: 2020 },
];
// {...}
Hiển thị lời giải mẫu
const { publisher: bookPublisher, ...restOfTheBook } = books[1];
console.log(bookPublisher); // O'Reilly
console.log(restOfTheBook); // { title: 'Book 2', year: 2020 }
3. Viết hàm printBookAuthorsCount
Viết hàm printBookAuthorsCount
với hai tham số title
và authors
.
authors
nhận số lượng đối số tùy ý.- Hàm in ra chuỗi theo định dạng:
"The book "${title}" has ${authors.length} authors"
Ví dụ:
printBookAuthorsCount("Algorithms", "Robert Sedgewick", "Kevin Wayne");
// Expected output: "The book "Algorithms" has 2 authors"
Hiển thị lời giải mẫu
function printBookAuthorsCount(title, ...authors) {
console.log(`The book "${title}" has ${authors.length} authors`);
}
Các em hãy luyện tập để hiểu rõ hơn về Rest Pattern và Rest Parameters nhé! Nếu có thắc mắc, cứ hỏi thầy nha!
Happy coding các em! ✨
— Thầy Đạt 🧡