Top những cách copy mảng, object mà lập trình viên JS không thể bỏ qua

Trường hợp mảng gồm các phần tử có kiểu dữ liệu primitive const input =[3,5,7,9]; Dùng toán tử spread const outputA1 =[...input]; Dùng slice không đối số const outputA2 = input.slice(); Đây là 2 cách tốt nhất, không những tối ưu về mặt hiệu năng mà cú pháp lại ngắn. Một số cách khác const

Trường hợp mảng gồm các phần tử có kiểu dữ liệu primitive

const input =[3,5,7,9];
  1. Dùng toán tử spread
const outputA1 =[...input];
  1. Dùng slice không đối số
const outputA2 = input.slice();

➡️ Đây là 2 cách tốt nhất, không những tối ưu về mặt hiệu năng mà cú pháp lại ngắn.

  1. Một số cách khác
const outputA3 =[].concat(input);const outputA4 = Array.from(input);const outputA5 = input.map(x=> x);const outputA6 = input.filter(()=>true);
  1. Sử dụng thư viện lodash
const outputA7 = _.clone(input);
  1. Không nên dùng JSON.parse &JSON.stringify để copy mảng chỉ chứa phần tử primitive
const outputA8 =JSON.parse(JSON.stringify(input));

Nó vẫn chạy và trả về kết quả như mong muốn nhưng không cần phải “dùng dao mổ trâu giết gà”. Cách này nên sử dụng để copy object hoặc mảng object.

Trường hợp mảng gồm các phần tử là object

const input2 =[{ name:"tony", age:18},{ name:"lisa", age:19}]

Đối với mảng chứa các phần tử là object nếu sử dụng những cách bên trên thì mảng mới được tạo ra chỉ chứa địa chỉ ô nhớ của các phần tử trước đó. Những phần tử là object ban đầu (lưu trong heap) vẫn chỉ có 1, chỉ là địa chỉ ô nhớ của nó được copy mà thôi, trường hợp này gọi là shallow copy, dịch ra tiếng Việt là copy một phần, copy không hoàn toàn,… Đây là kiểu copy không không an toàn vì nó vẫn còn “lưu luyến” với object cũ, thay đổi thuộc tính của phần tử trong mảng mới lại khiến mảng cũ bị thay đổi theo vì cùng trỏ tới 1 object trong heap.

Để xử lý trường hợp này ta cần phải tìm giải pháp deep copy được hiểu như cách mà bạn đang kỳ vọng, copy theo đúng nghĩa đen, copy hoàn toàn một object, không liên quan gì đến mảng cũ cả.


  1. Sử dung hàm structuredClone, đây là nativeAPI phạm vi global có sẵn trong javascript hỗ trợ hầu hết mọi trình duyệt ngoài trừ Internet Explorer & Samsung Internet.
const outputB1 =structuredClone(input2);
  1. Đây mới là lúc sử dụng JSON.parse & JSON.stringify
const outputB2 =JSON.parse(JSON.stringify(input2));
  1. Sử dụng lodash
const outputB3 =_cloneDeep(input2);

Trường hợp copy object có thuộc tính là các object lồng nhau nhiều cấp

const input3 ={
    name:"lisa",
    location:{
        province:{
            id:"HCM",
            name:"HCM City",
            zipCode:700000}}}

Ngoài ra JSON.parse/JSON.stringifystructuredClone còn được sử dụng để giải quyết trường hợp này.

const outputC1 =structuredClone(input3);const outputC2 =JSON.parse(JSON.stringify(input3));

➡️ Tóm lại** deep clone** object bằng structuredClone là cách tối ưu nhất. JSON.parse & JSON.stringify trông có vẻ như một trick, mẹo vặt.


Nếu bạn hiểu rõ cơ chế lưu data vào bộ nhớ stack, heap, nguyên lý phép gán, truyền tham chiếu, truyền tham trị, … thì sẽ dễ dàng phân biệt được shallow copydeep copy. Mình sẽ giải thích kỹ phần này ở post tiếp theo. Cái mà bạn nên quan tâm là phương pháp copy nào mang lại hiệu năng cao nhất, nhanh nhất khi xử lý một mảng khổng lồ mà API trả về, ví dụ như API này: https://finfo-api.vndirect.com.vn/v4/stock_prices?sort=date%3Adesc&q=floor%3AHOSE%2CHNX~type%3ASTOCK&fields=code%2Cdate%2Copen%2Chigh%2Clow%2Cclose%2CnmVolume%2Cchange%2CpctChange&size=100000&page=1

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ