Làm cách nào để gán đối tượng cho đối tượng khác trong JavaScript?

Một trong những khác biệt cơ bản của các đối tượng so với các đối tượng nguyên thủy là các đố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

let user = {
  name: "John"
};
7 vào
let user = {
  name: "John"
};
8

let message = "Hello!";
let phrase = message;

Kết quả là chúng ta có hai biến độc lập, mỗi biến lưu trữ chuỗi

let user = {
  name: "John"
};
9

Mộ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

let user = {
  name: "John"
};

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

let user = { name: "John" };

let admin = user; // copy the reference
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ư

let user = { name: "John" };

let admin = user; // copy the reference
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 một thuộc tính

let user = { name: "John" };

let admin = user; // copy the reference
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ụ

let user = { name: "John" };

let admin = user; // copy the reference

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ó

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference

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 (

let user = { name: "John" };

let admin = user; // copy the reference
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 (_______5_______0), chúng tôi vẫn mở cùng một tủ và có thể truy cập nội dung đã thay đổi

Hai đối tượng chỉ bằng nhau nếu chúng là cùng một đối tượng

Chẳng hạn, ở đây

let user = { name: "John" };

let admin = user; // copy the reference
5 và
let user = { name: "John" };

let admin = user; // copy the reference
6 tham chiếu cùng một đối tượng, do đó chúng bằng nhau

let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true

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)

let a = {};
let b = {}; // two independent objects

alert( a == b ); // false

Đối với các so sánh như

let user = { name: "John" };

let admin = user; // copy the reference
7 hoặc để so sánh với một
let user = { name: "John" };

let admin = user; // copy the reference
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 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à

let user = { name: "John" };

let admin = user; // copy the reference
9 có thể được sửa đổi

Ví dụ

const user = {
  name: "John"
};

user.name = "Pete"; // (*)

alert(user.name); // Pete

Có vẻ như dòng

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
0 sẽ gây ra lỗi, nhưng nó không. Giá trị của
let user = { name: "John" };

let admin = user; // copy the reference
0 là hằng số, nó phải luôn tham chiếu đến 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 đổi

Nói cách khác,

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
2 chỉ báo lỗi nếu chúng ta cố gắng đặt toàn bộ
let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
3

Đ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ả

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

let user = {
  name: "John",
  age: 30
};

let clone = {}; // the new empty object

// let's copy all user properties into it
for (let key in user) {
  clone[key] = user[key];
}

// now clone is a fully independent object with the same content
clone.name = "Pete"; // changed the data in it

alert( user.name ); // still John in the original object

Chúng ta cũng có thể sử dụng phương thức Object. giao phó

Cú pháp là

Object.assign(dest, ...sources)

  • Đối số đầu tiên
    let user = { name: 'John' };
    
    let admin = user;
    
    admin.name = 'Pete'; // changed by the "admin" reference
    
    alert(user.name); // 'Pete', changes are seen from the "user" reference
    4 là một đối tượng mục tiêu
  • Các đối số khác là danh sách các đối tượng nguồn

Nó sao chép các thuộc tính của tất cả các đối tượng nguồn vào

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
4 đích, sau đó trả về kết quả là

Ví dụ: chúng ta có đối tượng

let user = { name: "John" };

let admin = user; // copy the reference
0, hãy thêm một số quyền cho đối tượng đó

let user = { name: "John" };

let permissions1 = { canView: true };
let permissions2 = { canEdit: true };

// copies all properties from permissions1 and permissions2 into user
Object.assign(user, permissions1, permissions2);

// now user = { name: "John", canView: true, canEdit: true }
alert(user.name); // John
alert(user.canView); // true
alert(user.canEdit); // true

Nếu tên thuộc tính được sao chép đã tồn tại, nó sẽ bị ghi đè

let user = {
  name: "John"
};
0

Chúng ta cũng có thể sử dụng

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
7 để thực hiện nhân bản một đối tượng đơn giản

let user = {
  name: "John"
};
1

Tại đây, nó sao chép tất cả các thuộc tính của

let user = { name: "John" };

let admin = user; // copy the reference
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 trải rộng

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
9, sẽ được trình bày sau trong hướng dẫn

Cho đến bây giờ, chúng tôi giả định rằng tất cả các thuộc tính của

let user = { name: "John" };

let admin = user; // copy the reference
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ác

Như thế này

let user = {
  name: "John"
};
2

Bây giờ, việc sao chép

let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
1 là không đủ, vì
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
2 là một đối tượng và sẽ được sao chép theo tham chiếu, vì vậy,
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
3 và
let user = { name: "John" };

let admin = user; // copy the reference
0 sẽ có cùng kích thước

let user = {
  name: "John"
};
3

Để khắc phục điều đó và làm cho các đối tượng

let user = { name: "John" };

let admin = user; // copy the reference
0 và
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
3 thực sự tách biệt, chúng ta nên sử dụng vòng lặp nhân bản để kiểm tra từng giá trị của
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
7 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

Cuộc gọi

let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
8 sao chép
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
9 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

let user = {
  name: "John"
};
4

Phương thức

let a = {};
let b = {}; // two independent objects

alert( a == b ); // false
0 có thể sao chép hầu hết các kiểu 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ụ

let user = {
  name: "John"
};
5

Như bạn có thể thấy,

let a = {};
let b = {}; // two independent objects

alert( a == b ); // false
1 đề cập đến
let a = {};
let b = a; // copy the reference

alert( a == b ); // true, both variables reference the same object
alert( a === b ); // true
3, không phải
let user = { name: "John" };

let admin = user; // copy the reference
0. Vì vậy, tham chiếu vòng tròn cũng được sao chép chính xác

Mặc dù, có những trường hợp khi

let a = {};
let b = {}; // two independent objects

alert( a == b ); // false
0 thất bại

Chẳng hạn, khi một đối tượng có thuộc tính hàm

let user = {
  name: "John"
};
6

Thuộ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 nhân bản, viết mã tùy chỉnh hoặc để không phát minh lại bánh xe, hãy sử dụng triển khai hiện có, chẳng hạn như từ thư viện JavaScript lodash

Cá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

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // changed by the "admin" reference

alert(user.name); // 'Pete', changes are seen from the "user" reference
7 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”
let a = {};
let b = {}; // two independent objects

alert( a == b ); // false
0 hoặc sử dụng triển khai nhân bản tùy chỉnh, chẳng hạn như

Làm cách nào để thêm một đối tượng vào một đối tượng khác trong JavaScript?

Sử dụng phương thức gán () . Sử dụng phương thức gán(), chúng ta có thể gán hoặc thêm một giá trị mới cho một đối tượng hiện có hoặc chúng ta có thể tạo đối tượng mới mà không thay đổi các giá trị đối tượng hiện có.

Làm cách nào để gán giá trị của một đối tượng cho đối tượng khác trong JavaScript?

Đối tượng. gán() Đối tượng. phương thức tĩnh gán () sao chép 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. Nó trả về đối tượng mục tiêu đã sửa đổi.

Điều gì xảy ra khi bạn gán một đối tượng cho một đối tượng khác?

điều gì xảy ra khi bạn gán một đối tượng cho một đối tượng khác ?? . Nói cách khác, cả hai biến 'trỏ' đến cùng một Đối tượng. Ví dụ/ int [] a = new int[5]; . It assigns the reference of the Object. In other words, both variables 'point' to the same Object. For example/ int [] a = new int[5]; int [] b = a; b and a now 'point' to the same array.