Chúng ta đã biết object trong javascript là một con trỏ đến địa chỉ trên memory, copy 1 object sẽ là 2 biến trỏ tới cùng một địa chỉ memory
var foo = {
a: "luubinhan",
};
console.log(foo.a); // luubinhan
var bar = foo;
console.log(bar.a); // luubinhan
foo.a = "github";
console.log(foo.a); // github
console.log(bar.a); // github
bar.a = "google.com";
console.log(foo.a); // google.com
console.log(bar.a); // google.com
Có thể thấy là việc thay đổi 1 trong 2 biến foo
, bar
sẽ ảnh hưởng qua lại lẫn nhau, khi muốn thực hiện copy một object trong javascript phải hết sức cẩn thận
Shallow copy
Nếu các property bên trong của object là một giá trị primitive type, có thể thực hiện copy nhanh (shallow)
var obj = { foo: "foo", bar: "bar" };
// cách 1
var copy = { ...obj };
// cách 2
var copy2 = Object.assign({}, obj);
Nếu bên trong object là một tham chiếu khác, thì việc copy này sẽ cũng tương tự như var bar = foo
var foo = { a: 0, b: { c: 0 } };
var copy = { ...foo };
copy.a = 1;
copy.b.c = 2;
console.dir(foo); // {a: 0, b: {c: 2}}
console.dir(copy); // {a:1, b: {c: 2}}
Deep copy
Để tránh tình huống này xảy ra, chúng ta sẽ muốn thực hiện cái gọi là deep copy, trước tiên là serialize thành string rồi deserialize ngược lại
var obj = { a: 0, b: { c: 0 } };
var copy = JSON.parse(JSON.stringify(obj));
Lại tuy nhiên, nếu bên trong object là một giá trị không thể serialize như Date
object, ko thực hiện được.
Có thể dùng cloneDeep
của thư viện lodash là an toàn nhất để thực hiện Deep copy, còn nếu thích tự làm mọi thứ, thì đây là một hàm implement chức năng clone deep
function deepClone(obj) {
var copy;
// kiểu primitive, null hoặc undefined
if (null == obj || "object" != typeof obj) return obj;
// nếu là kiểu Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// kiểu Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// kiểu Function
if (obj instanceof Function) {
copy = function() {
return obj.apply(this, arguments);
};
return copy;
}
// kiểu Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error(
"Unable to copy obj as type isn't supported " + obj.constructor.name
);
}
Initializing...