JavaScript có nhiều cách để làm bất cứ điều gì. Tôi đã viết về 10 cách viết ống dẫn/soạn thảo bằng JavaScript và bây giờ chúng ta đang thực hiện mảng.
1. Toán tử trải rộng (Bản sao nông)
Kể từ khi ES6 bị loại bỏ, đây là phương pháp phổ biến nhất. Đó là một cú pháp ngắn gọn và bạn sẽ thấy nó vô cùng hữu ích khi sử dụng các thư viện như React và Redux.
numbers = [1, 2, 3];
numbersCopy = [...numbers];
Ghi chú: Điều này không sao chép mảng đa chiều một cách an toàn. Giá trị mảng/đối tượng được sao chép bởi thẩm quyền giải quyết thay vì bởi giá trị.
Điều này là tốt
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
Điều này không ổn
nestedNumbers = [[1], [2]];
numbersCopy = [...nestedNumbers];
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
2. Vòng lặp for() cũ tốt (Bản sao nông)
Tôi tưởng tượng cách tiếp cận này là ít nhất phổ biến, do lập trình chức năng hợp thời trang trở nên phổ biến như thế nào trong vòng kết nối của chúng tôi.
Tinh khiết hay không tinh khiết, tuyên bố hay mệnh lệnh, nó sẽ hoàn thành công việc!
numbers = [1, 2, 3];
numbersCopy = [];
for (i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
Ghi chú: Điều này không sao chép mảng đa chiều một cách an toàn. Vì bạn đang sử dụng =
toán tử, nó sẽ gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
Điều này là tốt
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
Điều này không ổn
nestedNumbers = [[1], [2]];
numbersCopy = [];
for (i = 0; i < nestedNumbers.length; i++) {
numbersCopy[i] = nestedNumbers[i];
}
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
3. Vòng lặp while() cũ tốt (Bản sao nông)
Giống như for
—không trong sạch, bắt buộc, blah, blah, blah…nó hoạt động! ?
numbers = [1, 2, 3];
numbersCopy = [];
i = -1;
while (++i < numbers.length) {
numbersCopy[i] = numbers[i];
}
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
Điều này là tốt
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
Điều này không ổn
nestedNumbers = [[1], [2]];
numbersCopy = [];
i = -1;
while (++i < nestedNumbers.length) {
numbersCopy[i] = nestedNumbers[i];
}
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
4. Array.map (Bản sao nông)
Quay trở lại lãnh thổ hiện đại, chúng ta sẽ tìm thấy map
chức năng. Bắt nguồn từ toán học, map
là khái niệm chuyển đổi một tập hợp thành một loại tập hợp khác mà vẫn bảo toàn cấu trúc.
Trong tiếng Anh, điều đó có nghĩa là Array.map
trả về một mảng có cùng độ dài mỗi lần.
Để nhân đôi một danh sách các số, hãy sử dụng map
với một double
chức năng.
numbers = [1, 2, 3];
double = (x) => x * 2;
numbers.map(double);
Thế còn nhân bản thì sao??
Đúng, bài viết này là về mảng nhân bản. Để sao chép một mảng, chỉ cần trả về phần tử trong map
cuộc gọi.
numbers = [1, 2, 3];
numbersCopy = numbers.map((x) => x);
Nếu bạn muốn toán học hơn một chút, (x) => x
được gọi là xác thực. Nó trả về bất kỳ tham số nào nó được đưa ra.
map(identity)
nhân bản một danh sách.
identity = (x) => x;
numbers.map(identity);
// [1, 2, 3]
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
5. Array.filter (Bản sao nông)
Hàm này trả về một mảng, giống như map
nhưng nó không đảm bảo có cùng độ dài.
Nếu bạn đang lọc các số chẵn thì sao?
[1, 2, 3].filter((x) => x % 2 === 0);
// [2]
Độ dài mảng đầu vào là 3, nhưng độ dài kết quả là 1.
Nếu là của bạn filter
vị ngữ của luôn trả về true
tuy nhiên, bạn nhận được một bản sao!
numbers = [1, 2, 3];
numbersCopy = numbers.filter(() => true);
Mọi phần tử đều vượt qua bài kiểm tra, vì vậy nó sẽ được trả lại.
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
6. Array.reduce (Bản sao nông)
Tôi gần như cảm thấy tồi tệ khi sử dụng reduce
để sao chép một mảng, bởi vì nó mạnh hơn thế rất nhiều. Nhưng chúng ta đi đây…
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);
reduce
biến đổi một giá trị ban đầu khi nó lặp qua một danh sách.
Ở đây, giá trị ban đầu là một mảng trống và chúng tôi sẽ điền vào nó với từng phần tử khi chúng tôi tiếp tục. Mảng đó phải được trả về từ hàm sẽ được sử dụng trong lần lặp tiếp theo.
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
7. Array.slice (Bản sao nông)
slice
trả về một Nông cạn bản sao của một mảng dựa trên chỉ mục bắt đầu/kết thúc được cung cấp mà bạn cung cấp.
Nếu chúng ta muốn 3 yếu tố đầu tiên:
[1, 2, 3, 4, 5].slice(0, 3);
// [1, 2, 3]
// Starts at index 0, stops at index 3
Nếu chúng ta muốn tất cả các phần tử, không đưa ra bất kỳ tham số nào
numbers = [1, 2, 3, 4, 5];
numbersCopy = numbers.slice();
// [1, 2, 3, 4, 5]
Ghi chú: Đây là một Nông cạn sao chép, vì vậy nó cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
8. JSON.parse và JSON.stringify (Bản sao sâu)
JSON.stringify
biến một đối tượng thành một chuỗi.
JSON.parse
biến một chuỗi thành một đối tượng.
Kết hợp chúng có thể biến một đối tượng thành một chuỗi, sau đó đảo ngược quy trình để tạo cấu trúc dữ liệu hoàn toàn mới.
Lưu ý: Cái này sao chép an toàn các đối tượng/mảng được lồng sâu!
nestedNumbers = [[1], [2]];
numbersCopy = JSON.parse(JSON.stringify(nestedNumbers));
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1], [2]]
// [[1, 300], [2]]
// These two arrays are completely separate!
9. Array.concat (Bản sao nông)
concat
kết hợp các mảng với các giá trị hoặc các mảng khác.
[1, 2, 3].concat(4); // [1, 2, 3, 4]
[1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5]
Nếu bạn không cung cấp gì hoặc một mảng trống, một bản sao nông sẽ được trả lại.
[1, 2, 3].concat(); // [1, 2, 3]
[1, 2, 3].concat([]); // [1, 2, 3]
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
10. Array.from (Bản sao nông)
Điều này có thể biến bất kỳ đối tượng có thể lặp lại nào thành một mảng. Đưa ra một mảng trả về một bản sao nông.
numbers = [1, 2, 3];
numbersCopy = Array.from(numbers);
// [1, 2, 3]
Ghi chú: Điều này cũng gán các đối tượng/mảng theo thẩm quyền giải quyết thay vì bởi giá trị.
Phần kết luận
Vâng, điều này là vui vẻ?
Tôi đã cố gắng sao chép chỉ bằng 1 bước. Bạn sẽ tìm thấy nhiều cách hơn nếu bạn sử dụng nhiều phương pháp và kỹ thuật.