Cú pháp spread (_______0_______9) cho phép một khả năng lặp lại, chẳng hạn như một mảng hoặc chuỗi, được mở rộng ở những nơi không có hoặc nhiều đối số (đối với lệnh gọi hàm) hoặc phần tử (đối với mảng ký tự) được mong đợi. Trong một đối tượng theo nghĩa đen, cú pháp trải rộng liệt kê các thuộc tính của một đối tượng và thêm các cặp khóa-giá trị vào đối tượng đang được tạo
Cú pháp lây lan trông giống hệt như cú pháp nghỉ ngơi. Theo một cách nào đó, cú pháp trải rộng ngược lại với cú pháp nghỉ ngơi. Cú pháp trải rộng "mở rộng" một mảng thành các phần tử của nó, trong khi cú pháp phần còn lại thu thập nhiều phần tử và "cô đặc" chúng thành một phần tử duy nhất. Xem phần còn lại thông số và
myFunction(a, ...iterableObj, b) [1, ...iterableObj, '4', 'five', 6] { ...obj, key: 'value' }
Cú pháp trải rộng có thể được sử dụng khi tất cả các phần tử từ một đối tượng hoặc mảng cần được đưa vào một mảng hoặc đối tượng mới hoặc nên được áp dụng từng cái một trong danh sách đối số của lệnh gọi hàm. Có ba nơi riêng biệt chấp nhận cú pháp lây lan
- danh sách (const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 0)
- (const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 1)
- (const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 2)
Mặc dù cú pháp trông giống nhau, nhưng chúng có ngữ nghĩa hơi khác nhau
Chỉ các đối tượng có thể lặp lại, như const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 3, mới có thể được trải rộng trong các tham số hàm và mảng. Nhiều đối tượng không thể lặp lại, bao gồm tất cả các đối tượng đơn giản thiếu phương thức const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 4
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable
Mặt khác, trải rộng trong nghĩa đen của đối tượng các thuộc tính riêng của đối tượng. Đối với các mảng điển hình, tất cả các chỉ số là vô số thuộc tính riêng, vì vậy các mảng có thể được trải thành các đối tượng
const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 }
Khi sử dụng cú pháp trải rộng cho các lệnh gọi hàm, hãy lưu ý khả năng vượt quá giới hạn độ dài đối số của công cụ JavaScript. Xem const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 5 để biết thêm chi tiết
Thay thế áp dụng()
Người ta thường sử dụng const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 5 trong trường hợp bạn muốn sử dụng các phần tử của mảng làm đối số cho hàm
function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args);
Với cú pháp lây lan ở trên có thể được viết là
function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args);
Bất kỳ đối số nào trong danh sách đối số đều có thể sử dụng cú pháp trải rộng và cú pháp trải rộng có thể được sử dụng nhiều lần
function myFunction(v, w, x, y, z) {} const args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
Áp dụng cho nhà điều hành mới
Khi gọi một hàm tạo với const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 7, không thể sử dụng trực tiếp một mảng và const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 8, bởi vì const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 8 gọi hàm mục tiêu thay vì xây dựng nó, điều đó có nghĩa là, trong số những thứ khác, rằng function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 0 sẽ là function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 1. Tuy nhiên, một mảng có thể dễ dàng sử dụng với const array = [1, 2, 3]; const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 } 7 nhờ cú pháp trải rộng
const dateFields = [1970, 0, 1]; // 1 Jan 1970 const d = new Date(...dateFields);
Một mảng mạnh hơn theo nghĩa đen
Nếu không có cú pháp trải rộng, để tạo một mảng mới bằng cách sử dụng một mảng hiện có như một phần của nó, thì cú pháp ký tự mảng không còn đủ và thay vào đó phải sử dụng mã bắt buộc bằng cách sử dụng kết hợp của function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 3, function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 4, function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 5, v.v. Với cú pháp lây lan, điều này trở nên ngắn gọn hơn nhiều
const parts = ['shoulders', 'knees']; const lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]
Giống như trải rộng cho danh sách đối số, const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 9 có thể được sử dụng ở bất kỳ đâu trong mảng chữ và có thể được sử dụng nhiều lần
Sao chép một mảng
const arr = [1, 2, 3]; const arr2 = [...arr]; // like arr.slice() arr2.push(4); // arr2 becomes [1, 2, 3, 4] // arr remains unaffected
Ghi chú. Cú pháp trải rộng hiệu quả đi sâu một cấp trong khi sao chép một mảng. Do đó, nó có thể không phù hợp để sao chép mảng nhiều chiều. Điều này cũng đúng với function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7 — không có hoạt động gốc nào trong JavaScript thực hiện một bản sao sâu. Phương pháp API web function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 8 cho phép sao chép sâu các giá trị nhất định
const a = [[1], [2], [3]]; const b = [...a]; b.shift().shift(); // 1 // Oh no! Now array 'a' is affected as well: console.log(a); // [[], [2], [3]]
Một cách tốt hơn để nối các mảng
function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 9 thường được sử dụng để nối một mảng vào cuối một mảng hiện có. Không có cú pháp trải rộng, điều này được thực hiện như
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 0
Với cú pháp trải rộng, điều này trở thành
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 1
function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args); 0 thường được sử dụng để chèn một mảng giá trị vào đầu một mảng hiện có. Không có cú pháp trải rộng, điều này được thực hiện như
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 2
Với cú pháp trải rộng, điều này trở thành
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 3
Ghi chú. Không giống như function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args); 1, điều này tạo ra một function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args); 2 mới, thay vì sửa đổi mảng function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args); 2 ban đầu tại chỗ
Có thể sao chép nông (không bao gồm nguyên mẫu) hoặc hợp nhất các đối tượng bằng cách sử dụng cú pháp ngắn hơn function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 4
Lưu ý rằng function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7 có thể được sử dụng để thay đổi một đối tượng, trong khi cú pháp lan truyền không thể
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 5
Ngoài ra, function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7 kích hoạt setters trên đối tượng đích, trong khi cú pháp trải rộng thì không
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 6
Bạn không thể triển khai lại hàm function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7 một cách ngây thơ thông qua một lần trải rộng
const obj = { key1: 'value1' }; const array = [...obj]; // TypeError: obj is not iterable 7
Trong ví dụ trên, cú pháp trải rộng không hoạt động như mong đợi. nó truyền một mảng đối số vào đối tượng theo nghĩa đen, do tham số còn lại. Đây là một triển khai của function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction(...args); 8 sử dụng cú pháp trải rộng, có hành vi tương tự như function myFunction(x, y, z) {} const args = [0, 1, 2]; myFunction.apply(null, args); 7, ngoại trừ việc nó không kích hoạt setters, cũng như không thay đổi bất kỳ đối tượng nào