Shallow Copy và Deep Copy trong Javascript

Spread the love

Hôm nay mình sẽ giới thiệu với các bạn về Shallow Copy và Deep Copy trong Javascript,
Trước khi đi chi tiết, chúng ta hãy thử làm một ví dụ sau

var bob = [1,2,3];
var sue = bob;
bob.push(4);
console.log("bob is:" + bob);
console.log("sue is:" + sue);

Với những ngôn ngữ khác như C#, C++ hay PHP, chắc hẳn nhiều bạn sẽ cho rằng kết quả phải được nhin như bên dưới là

bob is:1,2,3,4
sue is:1,2,3

Thế nhưng kết quả thì hơi khác, đoạn code trên sẽ in ra kết quả hoàn toàn khác với chúng ta nghĩ đấy là

bob is:1,2,3,4
sue is:1,2,3,4

Ô, vậy thì chuyện gì đang xảy ra ở đây nhỉ.
Có một cách lý giải rất đơn giản mà không đơn giản lắm đó là trong javascript các variable hoạt động giống như một con trỏ tự động nhiều hơn. Tức là với đoạn code trên, bạn có thay đổi bob hay sue bất kể lúc nào đi nữa, bạn vẫn luôn có chung một kết quả.

Vậy thì làm cách nào để khắc phục vấn đề shallow copy này nhỉ? Yeah, chắc các bạn cũng đã có câu trả lời giống như title của bài viết này, đó là dùng deep copy. Tất nhiên, có hằng hà sa cách để thực hiện deep copy. Dưới đây mình sẽ thực hiện cách khá gà trước.

Dùng foreach


var bob = [1,2,3];
var sue = [];
$.each(bob, function(key, row){
sue.push(row);
});
bob.push(4);
console.log(bob);
console.log(sue);

Tất nhiên là mọi người thường sẽ không thích cách này vì đơn giản là không phải lúc nào đối tượng bạn muốn clone cũng là array, hoặc bạn quá dị ứng với việc dùng vòng lặp để clone object. Hoặc là vì bạn không thích, v.v Nên ta sẽ đi sang cách thứ 2.

Dùng Json parse

Một sự hoan hô không hề nhẹ, và chúng ta cũng nên ngả mũ trước Douglas Crockford (!!!respect!!!) , một cách làm có tốc độ nhanh, đáp ứng nhu cầu sử dụng cho việc clone hàng trăm object.


var bob = [1,2,3];
var sue = (JSON.parse(JSON.stringify(bob)));
bob.push(4);
console.log(bob);
console.log(sue);

Cá nhân mình rất thích dùng JSON.parse…Đẹp trai =))!

Ngoài 2 cách trên,
Trường hợp bạn chỉ cần clone 1 vài object, bạn có thể dùng cách đỡ đẹp trai hơn đớ là dùng

$.extends
Chắc chắn nếu ai từng mày mò viết jQuery plugin đã quá quen thuộc với cú pháp này rồi
Ta thực hiện deep copy như sau


var bob = [1,2,3];
var sue = $.extend(true,{},bob);
bob.push(4);
console.log(bob);
console.log(sue);

Kết quả lúc này chắc chắn sẽ được in ra rất cụ thể đó là

bob is:1,2,3,4
sue is:1,2,3

Vậy là đã đúng với những gì ta nghĩ :P!

Đợt tới mình sẽ làm tiếp về loạt bài Pattern trong coding ;)!