“Bài này nằm trong loạt bài Kỹ thuật xử lý Javascript nâng cao (đang cập nhật) trên trang blog chính thức trungquandev. com“ Show Những nội dung có trong bài
1. Lặp đối tượng – lặp đối tượng trong JavascriptMình sẽ lần ví dụ triển khai theo 5 cách dưới đây, trong quá trình đi làm thực tế tùy theo những trường hợp yêu cầu khác nhau mà mình sẽ sử dụng từng cách để xử lý dữ liệu sao cho phù hợp nhất * cho…trong vòng lặpfor…in – giúp chúng ta lấy key của đối tượng trong mỗi lần lặp và có thể sử dụng key đó để lấy giá trị của đối tượng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } for (let key in object1) { if (object1.hasOwnProperty(key)) { console.log(`${key}: ${object1[key]}`) } } // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //
* Sự vật. phímSự vật. keys() sẽ nhận đối tượng của chúng ta làm tham số và trả về kết quả là một mảng (mảng) chứa tất cả các khóa của đối tượng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //
* Sự vật. giá trịĐối tượng. Các giá trị () sẽ nhận đối tượng của chúng ta làm tham số và trả về kết quả là một mảng (mảng) chứa tất cả giá trị của đối tượng. const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.values(object1)) // expected output: [17, "trungquan", "https://trungquandev.com"] Object.values(object1).forEach(value => { console.log(value) }) // expected output: // 17 // 'trungquan' // 'https://trungquandev.com' // * Sự vật. mụcSự vật. các mục() sẽ nhận đối tượng của chúng ta làm tham số và trả về một mảng mà bên trong đó lại tiếp tục là các mảng nhỏ hơn chứa các cặp khóa, giá trị của đối tượng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.entries(object1)) // expected output: [["id", 17], ["name", "trungquan"], ["website", "https://trungquandev.com"]] Object.entries(object1).forEach(([key, value]) => { console.log(`${key}: ${value}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //
* Sự vật. getOwnPropertyNamesSự vật. getOwnPropertyNames() sẽ nhận đối tượng của chúng ta làm tham số và trả về một mảng chứa các thuộc tính hoặc khóa (bao gồm cả thuộc tính không thể đánh số) của đối tượng Một trong những điểm khác biệt cơ bản của đối tượng so với đối tượng nguyên thủy là đối tượng được lưu trữ và sao chép “theo tham chiếu”, trong khi các giá trị nguyên thủy. chuỗi, số, boolean, v.v. – luôn được sao chép “dưới dạng toàn bộ giá trị” Điều đó dễ hiểu nếu chúng ta xem xét kỹ hơn điều gì sẽ xảy ra khi chúng ta sao chép một giá trị Hãy bắt đầu với một nguyên hàm, chẳng hạn như một chuỗi Ở đây chúng tôi đặt một bản sao của 7 vào 8
Kết quả là chúng ta có hai biến độc lập, mỗi biến lưu trữ chuỗi 9Một kết quả khá rõ ràng, phải không? Đối tượng không phải như vậy Một biến được gán cho một đối tượng không lưu trữ chính đối tượng đó, mà lưu trữ “địa chỉ của nó trong bộ nhớ” – nói cách khác là “một tham chiếu” đến nó Hãy xem một ví dụ về một biến như vậy
Và đây là cách nó thực sự được lưu trữ trong bộ nhớ Đối tượng được lưu trữ ở đâu đó trong bộ nhớ (ở bên phải của hình ảnh), trong khi biến 0 (ở bên trái) có một "tham chiếu" đến nóChúng ta có thể nghĩ về một biến đối tượng, chẳng hạn như 0, giống như một tờ giấy có địa chỉ của đối tượng trên đóKhi chúng ta thực hiện các thao tác với đối tượng, e. g. lấy thuộc tính 2, công cụ JavaScript xem xét địa chỉ đó có gì và thực hiện thao tác trên đối tượng thực tếBây giờ đây là lý do tại sao nó quan trọng Khi một biến đối tượng được sao chép, tham chiếu được sao chép, nhưng bản thân đối tượng không được sao chép Ví dụ
Bây giờ chúng ta có hai biến, mỗi biến lưu trữ một tham chiếu đến cùng một đối tượng Như bạn có thể thấy, vẫn còn một đối tượng, nhưng bây giờ có hai biến tham chiếu đến nó Chúng ta có thể sử dụng một trong hai biến để truy cập đối tượng và sửa đổi nội dung của nó const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //3 Như thể chúng ta có một chiếc tủ có hai chìa khóa và sử dụng một trong số chúng ( 3) để mở và thay đổi. Sau đó, nếu sau này chúng tôi sử dụng một chìa khóa khác ( 0), chúng tôi vẫn mở cùng một ngăn tủ và có thể truy cập nội dung đã thay đổiSo sánh bằng cách tham khảoHai đối tượng chỉ bằng nhau nếu chúng là cùng một đối tượng Chẳng hạn, ở đây 5 và 6 tham chiếu cùng một đối tượng, do đó chúng bằng nhauconst object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //8 Và ở đây, hai đối tượng độc lập không bằng nhau, mặc dù chúng trông giống nhau (cả hai đều trống rỗng) const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //9 Đối với các so sánh như 7 hoặc để so sánh với một 8 nguyên thủy, các đối tượng được chuyển đổi thành nguyên thủy. Chúng ta sẽ sớm nghiên cứu cách hoạt động của chuyển đổi đối tượng, nhưng nói thật, những phép so sánh như vậy rất hiếm khi cần thiết – chúng thường xuất hiện do lỗi lập trìnhĐối tượng const có thể được sửa đổi Một tác dụng phụ quan trọng của việc lưu trữ các đối tượng dưới dạng tham chiếu là một đối tượng được khai báo là 9 có thể được sửa đổiVí dụ const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.values(object1)) // expected output: [17, "trungquan", "https://trungquandev.com"] Object.values(object1).forEach(value => { console.log(value) }) // expected output: // 17 // 'trungquan' // 'https://trungquandev.com' //3 Có vẻ như dòng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //30 sẽ gây ra lỗi, nhưng không phải vậy. Giá trị của 0 là hằng số, nó phải luôn tham chiếu cùng một đối tượng, nhưng các thuộc tính của đối tượng đó có thể tự do thay đổiNói cách khác, const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //32 chỉ báo lỗi nếu chúng ta cố gắng đặt toàn bộ const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //33 Điều đó nói rằng, nếu chúng ta thực sự cần tạo các thuộc tính đối tượng không đổi, thì cũng có thể, nhưng sử dụng các phương thức hoàn toàn khác. Chúng tôi sẽ đề cập đến điều đó trong chương Cờ thuộc tính và bộ mô tả Nhân bản và hợp nhất, Đối tượng. giao phó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? Chúng ta có thể tạo một đối tượng mới và sao chép cấu trúc của đối tượng hiện có, bằng cách lặp lại các thuộc tính của nó và sao chép chúng ở cấp độ nguyên thủy Như thế này const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.values(object1)) // expected output: [17, "trungquan", "https://trungquandev.com"] Object.values(object1).forEach(value => { console.log(value) }) // expected output: // 17 // 'trungquan' // 'https://trungquandev.com' //8 Chúng ta cũng có thể sử dụng phương thức Object. giao phó Cú pháp là const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.values(object1)) // expected output: [17, "trungquan", "https://trungquandev.com"] Object.values(object1).forEach(value => { console.log(value) }) // expected output: // 17 // 'trungquan' // 'https://trungquandev.com' //9
Nó sao chép các thuộc tính của tất cả các đối tượng nguồn vào const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //34 đích, sau đó trả về nó dưới dạng kết quả Ví dụ: chúng tôi có đối tượng 0, hãy thêm một số quyền cho đối tượng đóconst object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.entries(object1)) // expected output: [["id", 17], ["name", "trungquan"], ["website", "https://trungquandev.com"]] Object.entries(object1).forEach(([key, value]) => { console.log(`${key}: ${value}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //3 Nếu tên thuộc tính được sao chép đã tồn tại, nó sẽ bị ghi đè 0Chúng ta cũng có thể sử dụng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //37 để thực hiện nhân bản một đối tượng đơn giản 1Tại đây, nó sao chép tất cả các thuộc tính của 0 vào đối tượng trống và trả vềNgoài ra còn có các phương pháp nhân bản đối tượng khác, chẳng hạn như. g. sử dụng cú pháp lây lan const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //39, được trình bày sau trong hướng dẫn nhân bản lồng nhauCho đến bây giờ chúng tôi giả định rằng tất cả các thuộc tính của 0 là nguyên thủy. Nhưng các thuộc tính có thể là tham chiếu đến các đối tượng khácNhư thế này 2Bây giờ, việc sao chép const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //81 là không đủ, vì const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //82 là một đối tượng và sẽ được sao chép theo tham chiếu, do đó, const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //83 và 0 sẽ có cùng kích thước 3Để khắc phục điều đó và làm cho các đối tượng thực sự tách biệt giữa 0 và const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //83, chúng ta nên sử dụng một vòng lặp nhân bản để kiểm tra từng giá trị của const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //87 và, nếu đó là một đối tượng, sau đó sao chép cả cấu trúc của nó. Đó được gọi là “nhân bản sâu” hoặc “nhân bản có cấu trúc”. Có phương pháp có cấu trúc Clone thực hiện nhân bản sâu cấu trúcCloneCuộc gọi const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //88 sao chép const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //89 với tất cả các thuộc tính lồng nhau Đây là cách chúng ta có thể sử dụng nó trong ví dụ của mình 4Phương thức const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //90 có thể sao chép hầu hết các loại dữ liệu, chẳng hạn như đối tượng, mảng, giá trị nguyên thủy Nó cũng hỗ trợ các tham chiếu vòng tròn, khi một thuộc tính đối tượng tham chiếu chính đối tượng đó (trực tiếp hoặc thông qua một chuỗi hoặc các tham chiếu) Ví dụ 5Như bạn có thể thấy, const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //91 đề cập đến const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //83, không phải 0. Vì vậy, tham chiếu vòng tròn cũng được sao chép chính xácMặc dù, có những trường hợp khi const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //90 thất bại Chẳng hạn, khi một đối tượng có thuộc tính hàm 6Thuộc tính chức năng không được hỗ trợ Để xử lý các trường hợp phức tạp như vậy, chúng tôi có thể cần sử dụng kết hợp các phương pháp sao chép, viết mã tùy chỉnh hoặc, để không phát minh lại bánh xe, chẳng hạn như triển khai _. cloneDeep(obj) từ thư viện JavaScript lodash Bản tóm tắtCác đối tượng được gán và sao chép theo tham chiếu. Nói cách khác, một biến lưu trữ không phải “giá trị đối tượng”, mà là “tham chiếu” (địa chỉ trong bộ nhớ) cho giá trị. Vì vậy, sao chép một biến như vậy hoặc chuyển nó dưới dạng đối số hàm sao chép tham chiếu đó, chứ không phải chính đối tượng đó Tất cả các hoạt động thông qua các tham chiếu được sao chép (như thêm/xóa thuộc tính) được thực hiện trên cùng một đối tượng Để tạo một “bản sao thực sự” (một bản sao), chúng ta có thể sử dụng const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //37 cho cái gọi là “bản sao nông” (các đối tượng lồng nhau được sao chép theo tham chiếu) hoặc chức năng “nhân bản sâu” const object1 = { id: 17, name: 'trungquan', website: 'https://trungquandev.com' } console.log(Object.keys(object1)) // expected output: ["id", "name", "website"] Object.keys(object1).forEach(key => { console.log(`${key}: ${object1[key]}`) }) // expected output: // 'id: 17' // 'name: trungquan' // 'website: https://trungquandev.com' //90 hoặc sử dụng triển khai nhân bản tùy chỉnh, chẳng hạn như _. cloneDeep(obj) |