Sao chép đối tượng JavaScript
Nếu bạn đang làm việc với JavaScript, việc xử lý các Đối tượng luôn khó khăn. Là người mới bắt đầu với JS, tôi đã gặp rất nhiều thử thách với Object nhưng giờ tôi đã hiểu rõ hơn về điều này và tôi muốn chia sẻ với tất cả các bạn Show
Điều đó có nghĩa là gì? let foo = "Hello String"; Bạn có thấy điều gì vừa xảy ra không? Khi bạn gán foo cho thanh, nó sẽ tạo một bản sao riêng của toàn bộ giá trị. Vì vậy, khi chúng tôi gán một giá trị mới cho thanh, nó không ảnh hưởng đến giá trị foo vì các nguyên hàm không sử dụng tham chiếu Trong khi nó hoàn toàn khác với Object Đối tượng là loại tham chiếu
Hãy hiểu nó bằng ví dụ let person = { name: 'Sarfraz' }; Như bạn có thể thấy, chỉ có một đối tượng ở đây với hai tham chiếu trỏ đến nó. Vì vậy, sao chép một biến đối tượng sẽ tạo thêm một tham chiếu đến cùng một đối tượng Nhưng nếu chúng ta cần sao chép một đối tượng thì sao? . Hãy xem 3 cách chúng ta có thể sao chép Đối tượng Sử dụng cú pháp Spread (…)Toán tử trải rộng nhân bản một đối tượng với các thuộc tính của nó. Hãy ghi nhớ là một bản sao nông, có nghĩa là chỉ các trường nguyên thủy cấp đầu tiên được sao chép theo giá trị và phần còn lại của các đối tượng lồng nhau được sao chép theo tham chiếu const dishes = { chicken: '🍗', pizza: '🍕' }; Sử dụng đối tượng. phương thức gán()đối tượng. Phương thức gán () được sử dụng để sao chép các giá trị của tất cả các thuộc tính riêng có thể đếm được từ một hoặc nhiều đối tượng nguồn sang đối tượng đích let obj = { a: 1, b: 2, }; Đối tượng sao chép sâu Một bản sao sâu sẽ sao chép mọi đối tượng mà nó gặp phải. Bản sao và đối tượng gốc sẽ không chia sẻ bất cứ thứ gì, vì vậy nó sẽ là bản sao của bản gốc. Điều này khắc phục sự cố mà chúng tôi gặp phải trong hai phương pháp trên Sử dụng JSON. phân tích cú pháp (JSON. xâu chuỗi (đối tượng))let obj = Phương pháp này có một số cạm bẫy. Nó không thể được sử dụng để sao chép các phương thức đối tượng do người dùng xác định và bạn phải đảm bảo rằng đối tượng nguồn là JSON an toàn Sử dụng _. phương thức cloneDeep()Các _. phương thức cloneDeep() được sử dụng để tạo một bản sao sâu của giá trị i. e. nó sao chép đệ quy giá trị const _ = require('lodash'); Vì đây là một bản sao sâu, bạn sẽ không có bất kỳ dấu vết nào đối với Đối tượng gốc Phần kết luậnSao chép các đối tượng trong JS có thể phức tạp, đặc biệt nếu bạn chưa quen với Javascript. Hy vọng rằng, bài viết này đã giúp bạn hiểu cách làm việc và tránh các vấn đề mà bạn có thể gặp phải sau này. Nếu bạn có bất kỳ đề xuất nào hoặc bất kỳ cách nào tốt hơn để đạt được điều này, vui lòng chỉ ra và tôi sẽ cập nhật nó. mã hóa hạnh phúc Trong bài viết này, bạn sẽ tìm hiểu sao chép nông và sâu là gì, cũng như cách tốt nhất để sao chép sâu một đối tượng trong JavaScript Sao chép nông vs. Sao chép sâuTrong thao tác gán lại liên quan đến các kiểu dữ liệu nguyên thủy như chuỗi, số và booleans, biến ban đầu được sao chép bởi JavaScript. Ví dụ: xem xét đoạn mã sau 1 let x = 3 2 y = x // x is copied into y let person = { name: 'Sarfraz' }; 0let person = { name: 'Sarfraz' }; 1let person = { name: 'Sarfraz' }; 2let person = { name: 'Sarfraz' }; 3let person = { name: 'Sarfraz' }; 4let person = { name: 'Sarfraz' }; 5let x = 30 let x = 31 Trong trường hợp này, giá trị let person = { name: 'Sarfraz' }; 031 được sao chép vào let person = { name: 'Sarfraz' }; 032, sau đó let person = { name: 'Sarfraz' }; 033 bị ngắt kết nối khỏi let person = { name: 'Sarfraz' }; 032. Vì vậy, đột biến let person = { name: 'Sarfraz' }; 032 không ảnh hưởng đến let person = { name: 'Sarfraz' }; 033Ngược lại, với các kiểu dữ liệu không nguyên thủy như mảng và đối tượng, chỉ một tham chiếu đến các giá trị được truyền. Vì vậy, khi bản sao bị biến đổi, bản gốc cũng bị biến đổi. Điều này còn được gọi là sao chép nông 1 let x = 33 2 let person = { name: 'Sarfraz' }; 0let x = 36 let person = { name: 'Sarfraz' }; 1let x = 38 let person = { name: 'Sarfraz' }; 3let person = { name: 'Sarfraz' }; 421 let x = 30 23 Thay vào đó, nếu chúng ta muốn sao chép một đối tượng để có thể sửa đổi nó mà không ảnh hưởng đến đối tượng ban đầu, chúng ta cần tạo một bản sao sâu. 5 cách để sao chép sâu các đối tượng trong JavaScriptTrong JavaScript, chúng ta có thể thực hiện sao chép đối tượng bằng các phương thức sau MethodProsConssao chép nông vớilet person = { name: 'Sarfraz' }; 037rõ ràng và trực tiếp, mặc định chỉ sao chép nông các đối tượnglet person = { name: 'Sarfraz' }; 038 và let person = { name: 'Sarfraz' }; 039sao chép sâu các đối tượng lồng nhau không sao chép chức năngObject. gán() sao chép các thành viên trực tiếp của một đối tượng—bao gồm các hàm không sao chép sâu các đối tượng lồng nhaucác toán tử trải rộng let person = { name: 'Sarfraz' }; 040 cú pháp đơn giản, cách ưa thích để sao chép một đối tượng không sao chép sâu các đối tượng lồng nhauLodash let person = { name: 'Sarfraz' }; 041sao chép các đối tượng lồng nhau bao gồm các hàmthêm một phụ thuộc bên ngoài vào dự án của bạnCác phương pháp này đều có ưu và nhược điểm. Chúng ta hãy xem xét kỹ hơn từng người trong số họ Sao chép nông một đối tượng theo nhiệm vụBạn có thể tạo một bản sao nông của một đối tượng bằng cách gán đối tượng ban đầu cho một biến mới. Xét đối tượng sau 1 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1y = x // x is copied into y1 let person = { name: 'Sarfraz' }; 3y = x // x is copied into y3 Để tạo một bản sao của đối tượng let person = { name: 'Sarfraz' }; 042, chúng ta gán đối tượng cho một biến mới như vậy1 y = x // x is copied into y5___ Theo quan sát trong đầu ra của bảng điều khiển, chúng tôi hiện đã sao chép đối tượng từ let person = { name: 'Sarfraz' }; 042 sang let person = { name: 'Sarfraz' }; 044Tuy nhiên, tất cả những gì chúng ta đã làm là tạo một tham chiếu đến đối tượng ban đầu. Bất cứ khi nào chúng ta thay đổi một thuộc tính trong đối tượng let person = { name: 'Sarfraz' }; 044, cuối cùng chúng ta cũng sẽ thay đổi đối tượng ban đầu (let person = { name: 'Sarfraz' }; 042) như chúng ta làm trong đoạn mã sauCác Vì vậy, khi một kiểu dữ liệu không nguyên thủy (mảng hoặc đối tượng) được gán cho một biến mới, JavaScript sẽ tạo một bản sao nông của đối tượng ban đầu Sao chép đối tượng bằng let person = { name: 'Sarfraz' };let person2 = person;person.name = 'John';console.log(person2.name); // "John" changes from person refernce038 và let person = { name: 'Sarfraz' };let person2 = person;person.name = 'John';console.log(person2.name); // "John" changes from person refernce039Phương thức let person = { name: 'Sarfraz' }; 038 nhận một đối tượng và tạo một chuỗi JSON từ nó. Phương thức let person = { name: 'Sarfraz' }; 039 phân tích cú pháp một chuỗi và trả về một đối tượng JavaScriptChúng ta có thể kết hợp cả hai phương pháp này để tạo một bản sao của đối tượng theo cách sau 1 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1y = x // x is copied into y1 let person = { name: 'Sarfraz' }; 3y = x // x is copied into y3 let person = { name: 'Sarfraz' }; 4let x = 30 let x = 312 let person = { name: 'Sarfraz' }; 06let person = { name: 'Sarfraz' }; 08y = x // x is copied into y8 let person = { name: 'Sarfraz' }; 10let person = { name: 'Sarfraz' }; 00let person = { name: 'Sarfraz' }; 12let person = { name: 'Sarfraz' }; 14let x = 320 let person = { name: 'Sarfraz' }; 16let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 18let person = { name: 'Sarfraz' }; 07let person = { name: 'Sarfraz' }; 20let person = { name: 'Sarfraz' }; 09let person = { name: 'Sarfraz' }; 22let person = { name: 'Sarfraz' }; 11let person = { name: 'Sarfraz' }; 24let person = { name: 'Sarfraz' }; 13let person = { name: 'Sarfraz' }; 26let person = { name: 'Sarfraz' }; 05let x = 333 let person = { name: 'Sarfraz' }; 07let x = 335 let person = { name: 'Sarfraz' }; 09let x = 337 let person = { name: 'Sarfraz' }; 11let x = 339 let person = { name: 'Sarfraz' }; 13let x = 341 let person = { name: 'Sarfraz' }; 27Khi đối tượng sao chép bị thay đổi, đối tượng ban đầu vẫn giữ nguyên 1 let x = 3444___ Tuy nhiên, có một lưu ý khi sử dụng phương pháp này. let person = { name: 'Sarfraz' }; 038 không sao chép chức năngGiả sử chúng ta có một phương thức trong đối tượng let person = { name: 'Sarfraz' }; 042 được gọi là let person = { name: 'Sarfraz' }; 0531 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1let x = 382 let person = { name: 'Sarfraz' }; 3let x = 384 let person = { name: 'Sarfraz' }; 4let x = 386 let x = 30 let x = 388 let person = { name: 'Sarfraz' }; 06y = x // x is copied into y3 Chức năng sẽ không khả dụng trong đối tượng được sao chép. Do đó, phương pháp này chỉ đạt được bản sao sâu nếu không có chức năng nào trong đối tượng Sao chép đối tượng bằng let person = { name: 'Sarfraz' };let person2 = person;person.name = 'John';console.log(person2.name); // "John" changes from person refernce054Trước ES6, let person = { name: 'Sarfraz' }; 054 là cách phổ biến nhất để sao chép sâu một đối tượng1 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1let x = 382 let person = { name: 'Sarfraz' }; 3let x = 384 let person = { name: 'Sarfraz' }; 4let x = 386 let x = 30 let x = 388 let person = { name: 'Sarfraz' }; 06y = x // x is copied into y3 let person = { name: 'Sarfraz' }; 08let person = { name: 'Sarfraz' }; 10209 let person = { name: 'Sarfraz' }; 054 sẽ sao chép mọi thứ vào đối tượng mới, bao gồm mọi chức năng. Thay đổi đối tượng được sao chép cũng không ảnh hưởng đến đối tượng ban đầu1 let x = 344 2 let person = { name: 'Sarfraz' }; 0y = x // x is copied into y8 let person = { name: 'Sarfraz' }; 1let person = { name: 'Sarfraz' }; 00let person = { name: 'Sarfraz' }; 3let person = { name: 'Sarfraz' }; 4let x = 320 let x = 30 let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 06223 let person = { name: 'Sarfraz' }; 08225 let person = { name: 'Sarfraz' }; 10227 let person = { name: 'Sarfraz' }; 12229 let person = { name: 'Sarfraz' }; 14231 let person = { name: 'Sarfraz' }; 16233 let person = { name: 'Sarfraz' }; 18let person = { name: 'Sarfraz' }; 13let person = { name: 'Sarfraz' }; 20let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 22239 let person = { name: 'Sarfraz' }; 24225 let person = { name: 'Sarfraz' }; 26227 let x = 333 229 let x = 335 231 let x = 337 233 let x = 339 let person = { name: 'Sarfraz' }; 13let x = 341 let person = { name: 'Sarfraz' }; 27Tuy nhiên, một điều cần nhớ về let person = { name: 'Sarfraz' }; 054 là phương thức này chỉ thực hiện sao chép sâu một phần đối tượngĐể hiểu điều đó có nghĩa là gì, chúng ta hãy xem xét những điều sau đây 1 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1let x = 382 let person = { name: 'Sarfraz' }; 3263 let person = { name: 'Sarfraz' }; 4265 let x = 30 let x = 388 let person = { name: 'Sarfraz' }; 06y = x // x is copied into y3 let person = { name: 'Sarfraz' }; 08let person = { name: 'Sarfraz' }; 10272 Theo quan sát, chúng tôi đã thêm thuộc tính vị trí và chuyển một đối tượng làm giá trị của nó. Bây giờ chúng ta có một cấu trúc phức tạp hơn chứa đối tượng lồng nhau. Bất cứ khi nào chúng ta thay đổi một thuộc tính trong đối tượng lồng nhau (trong let person = { name: 'Sarfraz' }; 044), nó cũng sẽ thay đổi thuộc tính tương tự trong đối tượng ban đầu (let person = { name: 'Sarfraz' }; 059). chúng ta hãy xem1 let x = 344 2 276 let person = { name: 'Sarfraz' }; 0let person = { name: 'Sarfraz' }; 1let person = { name: 'Sarfraz' }; 3y = x // x is copied into y8 let person = { name: 'Sarfraz' }; 4let person = { name: 'Sarfraz' }; 00let x = 30 let person = { name: 'Sarfraz' }; 06let x = 320 let person = { name: 'Sarfraz' }; 08let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 10let person = { name: 'Sarfraz' }; 07let person = { name: 'Sarfraz' }; 12let person = { name: 'Sarfraz' }; 09let person = { name: 'Sarfraz' }; 14293 let person = { name: 'Sarfraz' }; 16295 let person = { name: 'Sarfraz' }; 18297 let person = { name: 'Sarfraz' }; 20let person = { name: 'Sarfraz' }; 11let person = { name: 'Sarfraz' }; 22let person = { name: 'Sarfraz' }; 13let person = { name: 'Sarfraz' }; 24let person = { name: 'Sarfraz' }; 15let person = { name: 'Sarfraz' }; 26let person = { name: 'Sarfraz' }; 05let x = 333 let x = 366 let x = 335 let person = { name: 'Sarfraz' }; 09let x = 337 293 let x = 339 295 let x = 341 297 y = x // x is copied into y16 let person = { name: 'Sarfraz' }; 11y = x // x is copied into y18 let person = { name: 'Sarfraz' }; 13y = x // x is copied into y20 let person = { name: 'Sarfraz' }; 27Mặc dù thuộc tính let person = { name: 'Sarfraz' }; 060 trong đối tượng ban đầu vẫn không bị ảnh hưởng, nhưng thuộc tính let person = { name: 'Sarfraz' }; 061 đã bị thay đổi do thao tác chỉ định lạiDo đó, nên sử dụng phương thức let person = { name: 'Sarfraz' }; 054 để sao chép sâu các đối tượng không có đối tượng lồng nhau. Cách tốt nhất để sao chép sâu trong JavaScript. Toán tử lây lanMột cách khác để sao chép sâu các đối tượng trong JavaScript là sử dụng toán tử trải rộng ES6. Sử dụng dấu ba chấm ( let person = { name: 'Sarfraz' }; 040) thu thập tất cả các giá trị trên đối tượng ban đầu vào một đối tượng khác1 25 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1y = x // x is copied into y1 let person = { name: 'Sarfraz' }; 3y = x // x is copied into y3 let person = { name: 'Sarfraz' }; 4let x = 30 y = x // x is copied into y34 let person = { name: 'Sarfraz' }; 06let person = { name: 'Sarfraz' }; 08y = x // x is copied into y37 let person = { name: 'Sarfraz' }; 10let person = { name: 'Sarfraz' }; 12let x = 320 let person = { name: 'Sarfraz' }; 14let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 16let person = { name: 'Sarfraz' }; 07let person = { name: 'Sarfraz' }; 18let person = { name: 'Sarfraz' }; 09let person = { name: 'Sarfraz' }; 20__let person = { name: 'Sarfraz' }; 112_____122_____1Tuy nhiên, giống như với let person = { name: 'Sarfraz' }; 054, toán tử trải rộng chỉ tạo một bản sao một phần. Vì vậy, bất kỳ đối tượng nào có đối tượng lồng nhau sẽ không được sao chép sâuĐể tạo một bản sao sâu hoàn chỉnh với toán tử trải rộng, chúng ta sẽ phải viết một số mã bổ sung Xem xét cùng một đối tượng người dùng nhưng với một đối tượng lồng nhau 1 y = x // x is copied into y54 2 27 let person = { name: 'Sarfraz' }; 029 let person = { name: 'Sarfraz' }; 1let x = 382 let person = { name: 'Sarfraz' }; 3263 let person = { name: 'Sarfraz' }; 4y = x // x is copied into y64 let x = 30 let x = 388 let person = { name: 'Sarfraz' }; 06y = x // x is copied into y3 let person = { name: 'Sarfraz' }; 08let person = { name: 'Sarfraz' }; 10y = x // x is copied into y71 Để tránh làm thay đổi đối tượng ban đầu, đó là let person = { name: 'Sarfraz' }; 042, chúng ta phải trải rộng đối tượng sao chép trước khi thực hiện các thay đổi trực tiếp đối với bất kỳ thuộc tính nào của nó. Đối với bất kỳ đối tượng lồng nhau nào, chúng ta cũng phải trải rộng đối tượng con đó trước khi thực hiện thay đổi đối với bất kỳ thuộc tính nào của nó1 y = x // x is copied into y73 2 y = x // x is copied into y75 let person = { name: 'Sarfraz' }; 0y = x // x is copied into y77 let person = { name: 'Sarfraz' }; 1y = x // x is copied into y79 let person = { name: 'Sarfraz' }; 3y = x // x is copied into y81 let person = { name: 'Sarfraz' }; 4y = x // x is copied into y83 let x = 30 y = x // x is copied into y85 let person = { name: 'Sarfraz' }; 06y = x // x is copied into y3 Ở đây, chúng tôi đã biến đổi let person = { name: 'Sarfraz' }; 060, là thuộc tính cấp cao nhất trong let person = { name: 'Sarfraz' }; 044 và let person = { name: 'Sarfraz' }; 061, là thuộc tính phụLần này, thao tác trải rộng sẽ tạo ra một bản sao sâu hoàn chỉnh trong đó đối tượng ban đầu sẽ không bị ảnh hưởng bởi bất kỳ đột biến nào trên bản sao ( let person = { name: 'Sarfraz' }; 044)1 y = x // x is copied into y8 2 let person = { name: 'Sarfraz' }; 00let person = { name: 'Sarfraz' }; 0let person = { name: 'Sarfraz' }; 1let x = 320 let person = { name: 'Sarfraz' }; 3let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 4let person = { name: 'Sarfraz' }; 07let x = 30 let person = { name: 'Sarfraz' }; 09let person = { name: 'Sarfraz' }; 06293 let person = { name: 'Sarfraz' }; 08let person = { name: 'Sarfraz' }; 004let person = { name: 'Sarfraz' }; 10297 let person = { name: 'Sarfraz' }; 12let person = { name: 'Sarfraz' }; 11let person = { name: 'Sarfraz' }; 14let person = { name: 'Sarfraz' }; 13let person = { name: 'Sarfraz' }; 16let person = { name: 'Sarfraz' }; 15let person = { name: 'Sarfraz' }; 18let person = { name: 'Sarfraz' }; 05let person = { name: 'Sarfraz' }; 20let x = 366 let person = { name: 'Sarfraz' }; 22let person = { name: 'Sarfraz' }; 09let person = { name: 'Sarfraz' }; 24293 let person = { name: 'Sarfraz' }; 26295 let x = 333 297 let x = 335 let person = { name: 'Sarfraz' }; 11let x = 337 let person = { name: 'Sarfraz' }; 13let x = 339 let person = { name: 'Sarfraz' }; 27Sử dụng Lodash let person = { name: 'Sarfraz' };let person2 = person;person.name = 'John';console.log(person2.name); // "John" changes from person refernce041 để sao chép sâuLodash cũng cung cấp một phương thức tiện ích let person = { name: 'Sarfraz' }; 071 để sao chép sâu các đối tượng trong JavaScript. Đọc thêm về phương phápPhần kết luậnNhư bạn đã thấy, có một số cách để sao chép một biến trong JavaScript. Không có phương pháp nào là hoàn hảo cho mọi trường hợp, vì vậy bạn sẽ phải cẩn thận để chọn phương pháp tốt nhất cho từng tình huống Bạn có thể sao chép một đối tượng?Có một số cách để sao chép một đối tượng, phổ biến nhất là bằng một trình tạo bản sao hoặc nhân bản . Sao chép được thực hiện chủ yếu để bản sao có thể được sửa đổi hoặc di chuyển hoặc giữ nguyên giá trị hiện tại. Nếu một trong hai điều này là không cần thiết, thì việc tham chiếu đến dữ liệu gốc là đủ và hiệu quả hơn vì không xảy ra sao chép.
Làm cách nào để sao chép một đối tượng vào một đối tượng khác trong JavaScript?var clone = Đối tượng. gán({}, obj); . Phương thức gán () được sử dụng để sao chép các giá trị của tất cả các thuộc tính riêng có thể đếm được từ một hoặc nhiều đối tượng nguồn sang đối tượng đích
Làm cách nào để sao chép đối tượng tệp trong JavaScript?phương thức gán() . đối tượng. Phương thức gán () được sử dụng để sao chép các giá trị của tất cả các thuộc tính riêng có thể đếm được từ một hoặc nhiều đối tượng nguồn sang đối tượng đích.
Toán tử nào được sử dụng để sao chép một đối tượng trong JavaScript?assign() Một cách thay thế cho toán tử trải rộng là Đối tượng. phương thức gán(). Bạn sử dụng phương thức này để sao chép các giá trị và thuộc tính từ một hoặc nhiều đối tượng nguồn sang đối tượng đích. |