Spread Operator (…) trong JavaScript: Hướng dẫn & Ví dụ

Bạn đã bao giờ thấy dấu ba chấm (…) trong code JavaScript và tự hỏi nó là gì chưa? Đó chính là Spread Operator, một cú pháp cực kỳ mạnh mẽ trong ES6. Nó giúp bạn viết code ngắn gọn và dễ đọc hơn rất nhiều. Trong bài viết này, WiWeb sẽ cùng bạn tìm hiểu sâu về toán tử spread trong javascript, từ định nghĩa cơ bản đến các ví dụ ứng dụng thực tế trong công việc hàng ngày.

Spread Operator là gì? Giới thiệu cú pháp (…)

Spread Operator, hay javascript spread syntax, là một trong những tính năng hữu ích nhất được giới thiệu trong phiên bản ES6. Nó cho phép bạn “trải” hoặc “mở rộng” các phần tử của một đối tượng có thể lặp lại (iterable) như mảng, chuỗi, hoặc các thuộc tính của một đối tượng.

Định nghĩa và mục đích sử dụng chính

Mục đích chính của Spread Operator là để tách các phần tử của một mảng hoặc các thuộc tính của một đối tượng ra thành các yếu tố riêng lẻ. Thay vì phải dùng các vòng lặp hoặc các phương thức phức tạp, bạn có thể dùng dấu ba chấm ... để thực hiện công việc này một cách nhanh chóng. Điều này giúp code của bạn trở nên sạch sẽ, dễ hiểu và hiệu quả hơn rất nhiều.

Cú pháp cơ bản trong ES6

Cú pháp của nó vô cùng đơn giản: chỉ là ba dấu chấm ... đặt trước một mảng hoặc một đối tượng.

Ví dụ với mảng:

const numbers = [1, 2, 3];
console.log(...numbers); // Kết quả: 1 2 3

Ví dụ với đối tượng (từ ES2018):

const user = { name: 'WiWeb', job: 'Developer' };
const userClone = { ...user };
console.log(userClone); // Kết quả: { name: 'WiWeb', job: 'Developer' }

Trông đơn giản phải không? Giờ chúng ta hãy xem nó có thể làm được những gì nhé.

Spread Operator là gì? Giới thiệu cú pháp (...)
Spread Operator là gì? Giới thiệu cú pháp (…)

Ứng dụng Spread Operator với Mảng (Arrays)

Làm việc với mảng là một tác vụ thường xuyên trong JavaScript. Spread operator array mang đến một cách tiếp cận hiện đại và thanh lịch để xử lý các thao tác phổ biến.

Sao chép một mảng (Shallow Copy)

Trước đây, để sao chép một mảng, bạn có thể dùng slice() hoặc concat(). Nhưng với spread operator, việc này trở nên trực quan hơn bao giờ hết. Đây là một cách tuyệt vời để copy array using spread.

const originalFruits = ['Táo', 'Cam', 'Xoài'];
const copiedFruits = [...originalFruits];

copiedFruits.push('Nho'); // Thêm phần tử vào mảng sao chép

console.log(originalFruits); // ['Táo', 'Cam', 'Xoài'] - Mảng gốc không bị thay đổi
console.log(copiedFruits);   // ['Táo', 'Cam', 'Xoài', 'Nho']

Lưu ý quan trọng: Đây là một shallow copy (sao chép nông). Nếu mảng của bạn chứa các đối tượng hoặc mảng khác, chỉ có tham chiếu đến chúng được sao chép, không phải bản thân các đối tượng đó.

Nối (concatenate) nhiều mảng lại với nhau

Thay vì dùng phương thức concat(), bạn có thể dùng spread operator để gộp nhiều mảng một cách dễ dàng.

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const array3 = [7, 8, 9];

const mergedArray = [...array1, ...array2, ...array3];
console.log(mergedArray); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

Cách này không chỉ ngắn gọn hơn mà còn linh hoạt hơn khi bạn muốn thêm các phần tử riêng lẻ vào giữa các mảng.

Thêm phần tử mới vào một mảng một cách bất biến (immutable)

Trong lập trình hiện đại, đặc biệt là khi làm việc với các thư viện như React, tính bất biến (immutability) rất quan trọng. Spread operator giúp bạn thêm phần tử mới vào mảng mà không làm thay đổi mảng ban đầu.

const todos = ['Học JavaScript', 'Làm bài tập'];

// Thêm vào cuối mảng
const newTodosEnd = [...todos, 'Đi ngủ'];

// Thêm vào đầu mảng
const newTodosStart = ['Thức dậy', ...todos];

console.log(todos); // Mảng gốc vẫn giữ nguyên!
console.log(newTodosEnd);
console.log(newTodosStart);
Ứng dụng Spread Operator với Mảng (Arrays)
Ứng dụng Spread Operator với Mảng (Arrays)

Ứng dụng Spread Operator với Đối tượng (Objects)

Kể từ phiên bản ES2018, spread operator object cũng đã trở thành một công cụ không thể thiếu khi làm việc với các đối tượng trong JavaScript. Các nguyên tắc cũng tương tự như với mảng.

Sao chép một đối tượng (Shallow Copy)

Giống như mảng, bạn có thể dễ dàng tạo một bản sao (nông) của một đối tượng.

const originalUser = {
  name: 'WiWeb',
  contact: { email: 'contact@wiweb.vn' }
};

const copiedUser = { ...originalUser };

copiedUser.name = 'WiWeb Team'; // Thay đổi thuộc tính của bản sao

console.log(originalUser.name); // 'WiWeb' - Đối tượng gốc không đổi
console.log(copiedUser.name);   // 'WiWeb Team'

Gộp (merge) nhiều đối tượng lại với nhau

Đây là một trong những ứng dụng mạnh mẽ nhất. Bạn có thể gộp nhiều đối tượng để tạo thành một đối tượng mới. Nếu có các thuộc tính trùng lặp, thuộc tính của đối tượng sau cùng sẽ ghi đè lên thuộc tính của đối tượng trước đó.

const basicInfo = { name: 'Thành', age: 25 };
const jobInfo = { job: 'Content Writer', company: 'WiWeb' };
const moreInfo = { age: 26, city: 'Hanoi' }; // Thuộc tính 'age' sẽ ghi đè

const fullInfo = { ...basicInfo, ...jobInfo, ...moreInfo };

console.log(fullInfo);
// { name: 'Thành', age: 26, job: 'Content Writer', company: 'WiWeb', city: 'Hanoi' }

Cập nhật thuộc tính của đối tượng

Spread operator là cách hoàn hảo để cập nhật một vài thuộc tính của đối tượng mà vẫn giữ nguyên các thuộc tính khác. Cách làm này cũng đảm bảo tính bất biến.

const book = {
  title: 'Lập trình JavaScript',
  author: 'WiWeb',
  pages: 200
};

const updatedBook = { ...book, pages: 250 }; // Cập nhật số trang

console.log(updatedBook);
// { title: 'Lập trình JavaScript', author: 'WiWeb', pages: 250 }
Ứng dụng Spread Operator với Đối tượng (Objects)
Ứng dụng Spread Operator với Đối tượng (Objects)

Sử dụng Spread Operator trong lời gọi Hàm (Functions)

Spread operator cũng rất hữu ích khi bạn cần truyền các đối số cho một hàm. Nó giúp biến các phần tử của một mảng thành một danh sách các đối số riêng lẻ.

Truyền các phần tử mảng làm đối số cho hàm

Giả sử bạn có một hàm nhận nhiều đối số, và bạn lại có các đối số này nằm trong một mảng. Spread operator sẽ giúp bạn giải quyết vấn đề này một cách gọn gàng.

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [10, 20, 30];

// Cách cũ dùng apply()
// const result = sum.apply(null, numbers);

// Cách mới với Spread Operator
const result = sum(...numbers);

console.log(result); // 60

Bạn thấy không? Cách dùng spread operator dễ đọc và dễ hiểu hơn nhiều.

Ví dụ thực tế với hàm Math.max()

Hàm Math.max() dùng để tìm số lớn nhất trong một danh sách các số. Tuy nhiên, nó không chấp nhận một mảng làm đối số. Đây chính là lúc spread operator tỏa sáng.

const numberList = [5, 12, 8, 25, 3];

// Math.max(numberList) sẽ báo lỗi

const maxNumber = Math.max(...numberList);

console.log(maxNumber); // 25

Thật đơn giản và hiệu quả!

Sử dụng Spread Operator trong lời gọi Hàm (Functions)
Sử dụng Spread Operator trong lời gọi Hàm (Functions)

So sánh chi tiết: Spread Operator và Rest Parameters

Đây là một điểm rất dễ gây nhầm lẫn cho người mới bắt đầu. Cả Rest vs Spread Operator đều dùng cú pháp ... nhưng chúng hoàn toàn trái ngược nhau về mục đích.

Sự giống nhau: Cùng sử dụng cú pháp (…)

Điểm chung duy nhất và cũng là nguồn gốc của sự nhầm lẫn chính là cả hai đều sử dụng ba dấu chấm. Tuy nhiên, ngữ cảnh sử dụng sẽ quyết định nó là Spread hay Rest.

Sự khác biệt cốt lõi: Ngữ cảnh và mục đích

  • Spread Operator (Toán tử Rải): Mở rộng hoặc trải các phần tử của một iterable (mảng, chuỗi) hoặc thuộc tính của một đối tượng ra thành các phần tử riêng lẻ. Nó được dùng ở nơi cần nhiều giá trị, như trong lời gọi hàm, mảng, hoặc đối tượng.
  • Rest Parameters (Tham số Còn lại): Gom nhiều phần tử riêng lẻ lại thành một mảng duy nhất. Nó chỉ được dùng trong danh sách tham số của hàm để lấy các đối số còn lại.

Bảng tóm tắt và ví dụ giúp phân biệt rõ ràng

Tiêu chíSpread OperatorRest Parameters
Mục đíchTrải ra (Expand)Gom lại (Collect)
Vị trí sử dụngLời gọi hàm, khai báo mảng/đối tượngKhai báo tham số của hàm, trong phép gán hủy cấu trúc (destructuring)
Kết quảCác phần tử/thuộc tính riêng lẻMột mảng duy nhất

Ví dụ về Spread:

const numbers = [1, 2, 3];
const newArray = [...numbers, 4, 5]; // Trải mảng numbers ra
console.log(newArray); // [1, 2, 3, 4, 5]

Ví dụ về Rest:

function collectArgs(firstArg, ...restOfArgs) { // Gom các đối số còn lại
  console.log('Đối số đầu tiên:', firstArg);
  console.log('Các đối số còn lại:', restOfArgs);
}

collectArgs('a', 'b', 'c', 'd');
// Đối số đầu tiên: a
// Các đối số còn lại: ['b', 'c', 'd']

Hiểu được sự khác biệt này là một bước tiến lớn trong việc làm chủ JavaScript hiện đại.

So sánh chi tiết: Spread Operator và Rest Parameters
So sánh chi tiết: Spread Operator và Rest Parameters

Tại sao Spread Operator lại hữu ích trong React?

Trong lĩnh vực phát triển web với React, spread operator không chỉ hữu ích mà gần như là một công cụ không thể thiếu. Nó giúp xử lý hai tác vụ quan trọng: truyền props và cập nhật state.

Truyền props cho component

Khi một component cha có nhiều props cần truyền xuống component con, việc liệt kê từng cái một có thể rất dài dòng. Spread operator giúp bạn chuyển tiếp tất cả props một cách gọn gàng.

function UserProfile(props) {
  // props có thể là { name: 'WiWeb', avatar: 'url' }
  return <Avatar {...props} />; // Trải tất cả props vào component Avatar
}

function Avatar({ name, avatar }) {
  return <img src={avatar} alt={name} />;
}

Cách làm này giúp code sạch sẽ và dễ bảo trì hơn rất nhiều.

Cập nhật state một cách bất biến (immutability)

React hoạt động dựa trên nguyên tắc bất biến. Bạn không bao giờ được thay đổi trực tiếp state hoặc props. Thay vào đó, bạn phải tạo ra một bản sao mới với những thay đổi cần thiết. Spread operator là công cụ hoàn hảo cho việc này.

Cập nhật một đối tượng trong state:

// Giả sử state hiện tại
// this.state = { user: { name: 'Thành', age: 25 } };

// Cập nhật tuổi mà không thay đổi tên
this.setState(prevState => ({
  user: {
    ...prevState.user, // Sao chép tất cả thuộc tính cũ
    age: 26            // Ghi đè thuộc tính cần thay đổi
  }
}));

Thêm một mục vào mảng trong state:

// Giả sử state hiện tại
// this.state = { items: ['item1', 'item2'] };

this.setState(prevState => ({
  items: [...prevState.items, 'item3'] // Tạo mảng mới với phần tử mới
}));

Sử dụng spread operator đảm bảo bạn tuân thủ các nguyên tắc của React, giúp ứng dụng hoạt động ổn định và dễ dự đoán hơn.

Tại sao Spread Operator lại hữu ích trong React?
Tại sao Spread Operator lại hữu ích trong React?

Kết luận

Spread Operator là một công cụ cực kỳ linh hoạt và mạnh mẽ trong JavaScript. Bạn nên sử dụng nó bất cứ khi nào bạn muốn:

  • Tạo bản sao (nông) của mảng hoặc đối tượng.
  • Nối các mảng hoặc gộp các đối tượng lại với nhau.
  • Thêm/cập nhật phần tử/thuộc tính một cách bất biến.
  • Truyền các phần tử của mảng làm đối số cho hàm.

Việc thành thạo toán tử spread trong javascript sẽ giúp code của bạn không chỉ ngắn gọn hơn mà còn dễ đọc và tuân thủ các-quy-tắc lập trình hiện đại.

Bạn còn trường hợp sử dụng Spread Operator nào thú vị muốn chia sẻ không? Hãy để lại bình luận bên dưới nhé!

Nếu bạn cần một website chuyên nghiệp để phát triển thương hiệu, WiWeb luôn sẵn sàng tư vấn. Liên hệ với chúng tôi nhé!

5/5 - (85 Đánh giá)
Bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *