Googling cho "đối tượng nhân bản javascript" mang lại một số kết quả thực sự kỳ lạ, một số trong số chúng đã lỗi thời và một số quá phức tạp, không dễ như vậy:
let clone = {...original};
Có gì không ổn với điều này?
Googling cho "đối tượng nhân bản javascript" mang lại một số kết quả thực sự kỳ lạ, một số trong số chúng đã lỗi thời và một số quá phức tạp, không dễ như vậy:
let clone = {...original};
Có gì không ổn với điều này?
Câu trả lời:
Điều này là tốt cho nhân bản nông . Sự lan truyền đối tượng là một phần tiêu chuẩn của ECMAScript 2018 .
Để nhân bản sâu, bạn sẽ cần một giải pháp khác .
const clone = {...original}
nhân bản nông
const newobj = {...original, prop: newOne}
để bất động thêm một chỗ dựa khác vào bản gốc và lưu trữ như một đối tượng mới.
JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
sẽ không hoạt động, bởi vì nếu có functions
hoặc infinity
dưới dạng giá trị, nó sẽ chỉ gán null
ở vị trí của chúng. Nó sẽ chỉ hoạt động nếu các giá trị đơn giản literals
và không functions
.
EDIT: Khi câu trả lời này được đăng, {...obj}
cú pháp không có sẵn trong hầu hết các trình duyệt. Ngày nay, bạn sẽ ổn khi sử dụng nó (trừ khi bạn cần hỗ trợ IE 11).
Sử dụng Object.assign.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
Tuy nhiên, điều này sẽ không tạo ra một bản sao sâu sắc. Cho đến nay vẫn chưa có cách nhân bản sâu.
EDIT: Như @Mike 'Pomax' Kamermans đã đề cập trong các bình luận, bạn có thể sao chép sâu các đối tượng đơn giản (ví dụ: không có nguyên mẫu, hàm hoặc tham chiếu vòng tròn) bằng cách sử dụng JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
là một bản sao sâu thích hợp. Tuy nhiên, các nguyên mẫu thời điểm, chức năng hoặc tham chiếu vòng tròn đang hoạt động, giải pháp đó không còn hoạt động.
Nếu các phương thức bạn đã sử dụng không hoạt động tốt với các đối tượng liên quan đến các loại dữ liệu như Ngày , hãy thử điều này
Nhập khẩu _
import * as _ from 'lodash';
Đối tượng nhân bản sâu
myObjCopy = _.cloneDeep(myObj);
import _ from 'lodash';
là đủ. Nhưng +1 cho câu trả lời "không phát minh lại bánh xe".
nếu bạn không muốn sử dụng json.parse (json.opesify (object)), bạn có thể tạo các bản sao khóa-giá trị đệ quy:
function copy(item){
let result = null;
if(!item) return result;
if(Array.isArray(item)){
result = [];
item.forEach(element=>{
result.push(copy(element));
});
}
else if(item instanceof Object && !(item instanceof Function)){
result = {};
for(let key in item){
if(key){
result[key] = copy(item[key]);
}
}
}
return result || item;
}
Nhưng cách tốt nhất là tạo một lớp có thể tự trả về một bản sao của nó
class MyClass{
data = null;
constructor(values){ this.data = values }
toString(){ console.log("MyClass: "+this.data.toString(;) }
remove(id){ this.data = data.filter(d=>d.id!==id) }
clone(){ return new MyClass(this.data) }
}
Theo dõi câu trả lời của @marcel, tôi thấy một số chức năng vẫn còn thiếu trên đối tượng nhân bản. ví dụ
function MyObject() {
var methodAValue = null,
methodBValue = null
Object.defineProperty(this, "methodA", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
},
enumerable: true
});
Object.defineProperty(this, "methodB", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
}
});
}
trong đó trên MyObject tôi có thể sao chép phương thứcA nhưng phương thứcB đã bị loại trừ. Điều này xảy ra vì nó bị mất
enumerable: true
có nghĩa là nó đã không xuất hiện trong
for(let key in item)
Thay vào đó tôi chuyển sang
Object.getOwnPropertyNames(item).forEach((key) => {
....
});
trong đó sẽ bao gồm các phím không đếm được.
Tôi cũng thấy rằng nguyên mẫu ( proto ) không được nhân bản. Cho rằng tôi đã kết thúc bằng cách sử dụng
if (obj.__proto__) {
copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
PS: Thật khó chịu khi tôi không thể tìm thấy một hàm tích hợp để làm điều này.
Bạn có thể làm nó như thế này là tốt,
let copiedData = JSON.parse(JSON.stringify(data));
We can do that with two way:
1- First create a new object and replicate the structure of the existing one by iterating
over its properties and copying them on the primitive level.
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 independant clone
clone.name = "Pete"; // changed the data in it
alert( user.name ); // still John in the original object
2- Second we can use the method Object.assign for that
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);
-Another example
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.
Nhưng Object.assign () không tạo bản sao sâu
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, same object
// user and clone share sizes
user.sizes.width++; // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one
Để khắc phục điều đó, 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 người dùng [khóa] và, nếu đó là một đối tượng, thì cũng sao chép cấu trúc của nó. Điều đó được gọi là một bản sao nhân bản sâu.
Có một thuật toán tiêu chuẩn để nhân bản sâu xử lý trường hợp trên và các trường hợp phức tạp hơn, được gọi là thuật toán nhân bản có cấu trúc . Để không phát minh lại bánh xe, chúng ta có thể sử dụng thực hiện hoạt động của nó ra khỏi thư viện JavaScript lodash phương pháp này được gọi là _.cloneDeep (obj) .
Tất cả các phương pháp trên không xử lý nhân bản sâu các đối tượng nơi nó được lồng đến n cấp. Tôi đã không kiểm tra hiệu suất của nó so với những người khác nhưng nó ngắn và đơn giản.
Ví dụ đầu tiên bên dưới cho thấy nhân bản đối tượng bằng cách sử dụng bản sao Object.assign
nào cho đến cấp đầu tiên.
var person = {
name:'saksham',
age:22,
skills: {
lang:'javascript',
experience:5
}
}
newPerson = Object.assign({},person);
newPerson.skills.lang = 'angular';
console.log(newPerson.skills.lang); //logs Angular
Sử dụng cách tiếp cận dưới đây đối tượng nhân bản sâu
var person = {
name:'saksham',
age:22,
skills: {
lang:'javascript',
experience:5
}
}
anotherNewPerson = JSON.parse(JSON.stringify(person));
anotherNewPerson.skills.lang = 'angular';
console.log(person.skills.lang); //logs javascript
original = { a: [1,2,3] }
cung cấp cho bạn một bản sao vớiclone.a
nghĩa đenoriginal.a
. Sửa đổi thông qua một trong haiclone
hoặcoriginal
sửa đổi điều tương tự , vì vậy không, điều này là xấu =)