Value vs Reference trong Javascript
Bài đăng này đã không được cập nhật trong 3 năm
Javascript có 5 kiểu dữ liệu đc truyền bằng value: Boolean, null, undefined, String và Number. Chúng ta gọi đó là kiểu dữ liệu nguyên thủy. Javascript có 3 kiểu dữ liệu đc truyền bằng reference: Array, Function, Object. Chúng về căn bản cũng là Object, do vậy ta sẽ gọi chung chúng là Object
Kiểu dữ liệu nguyên thuỷ
Nếu một kiểu dữ liệu nguyên thủy đc gán cho biến, chúng ta coi biến đó chứa dữ liệu nguyên thủy.
var x = 10;
var y = 'abc';
var z = null;
x chứa 10, y chứa 'abc'. Để dễ hình dùng, những biến và value tương ứng của chúng trông như này trong bộ nhớ.
Khi chúng ta gán những biến đó cho biến khác bằng cách sử dụng =, chúng ta copy value đó cho biến mới. Nói cách khác, chúng đc copy bởi value.
var x = 10;
var y = 'abc';
var a = x;
var b = y;
console.log(x, y, a, b); // -> 10, 'abc', 10, 'abc'
Cả a và x bây h đều chứa 10. Cả b và y đều chứa 'abc'. Chúng hoàn toàn độc lập, vì chỉ những value đã đc copy.
Thay đổi một cái sẽ ko thay đổi cái còn lại. Những biến đó ko có mối quan hệ gì với nhau cả.
var x = 10;
var y = 'abc';
var a = x;
var b = y;
a = 5;
b = 'def';
console.log(x, y, a, b); // -> 10, 'abc', 5, 'def'
Objects
Những biến đc gán kiểu dữ liệu ko nguyên thủy sẽ đc đưa cho reference đến value đó. Reference đó chỉ đến vị trí của object trong bộ nhớ. Những biến đó ko thực sự chứa value. Object đc tạo ra ở một chỗ nào đó trong bộ nhớ. Khi chúng ta viết arr = [], chúng ta đã tạo một mảng trong bộ nhớ. Thứ mà biến arr nhận đc là địa chỉ, vị trí của mảng đó. Khi chúng ta gán và sữ dụng một biến kiểu reference, thứ mà chúng ta viết và nhìn sẽ là:
1) var arr = [];
2) arr.push(1);
Biểu diễn của dòng 1 và dòng 2 trong bộ nhớ sẽ như sau: Dòng 1: Dòng 2:
Chú ý rằng value, địa chỉ chứa trong arr ko bị thay đổi. Mảng trong bộ nhớ mới là thứ bị thay đổi. Khi chúng ta sử dụng arr để làm gì đó, ví dụ như push thêm value, javascript engine đi đến vị trí của biến arr ở trong bộ nhớ và làm việc với giá trị đc lưu trữ ở đó.
Gán bằng Reference
Khi một giá trị kiểu reference, một object đc copy sang biến khác bằng cách sử dụng =, địa chỉ của giá trị đó mới là thứ thực sự đc copy. Object được copy bởi reference chứ ko phải là value.
var reference = [1];
var refCopy = reference;
Đoạn code trên trông giống như này ở trong bộ nhớ:
Mỗi biến giờ đều chứa reference đến cùng một mảng. Điều đó nghĩa là nếu chúng ta thay đổi reference, refCopy cũng bị đổi theo:
Each variable now contains a reference to the same array. That means that if we alter reference, refCopy will see those changes:
reference.push(2);
console.log(reference, refCopy); // -> [1, 2], [1, 2]
Chúng ta đã push 2 vào mảng ở trong bộ nhớ. Khi chúng ta dùng reference và refCopy, chúng ta chỉ đến cùng một mảng đó.
Gán lại một Reference
Gán lại một biến kiểu reference sẽ thay thế reference cũ.
var obj = { first: 'reference' };
Trong bộ nhớ: Khi chúng ta thêm dòng thứ hai
var obj = { first: 'reference' };
obj = { second: 'ref2' }
Địa chỉ đc lưu trong obj thay đổi. Object đầu tiên vẫn còn trong bộ nhớ, và object tiếp theo cũng vậy:
Khi ko còn một reference nào đến một object nữa, giống như địa chỉ #234 ở trên, javascript engine sẽ tiến hành garbage collection. Điều này nghĩa là programmer đã mất reference đến object đó và sẽ ko thể dùng nó nữa, do vậy engine sẽ tiến hành delete nó khỏi bộ nhớ.
== và ===
Khi toán tử == và === đc dùng với biến kiểu reference, chúng kiểm tra reference đó. Nếu hai biến đó chứa reference đến cùng một thứ, kết quả so sánh sẽ là true.
var arrRef = [’Hi!’];
var arrRef2 = arrRef;
console.log(arrRef === arrRef2); // -> true
Nếu chúng là những object khác nhau, kể cả chúng có nội dung giống hệt nhau, kết quả vẫn ra false.
var arr1 = ['Hi!'];
var arr2 = ['Hi!'];
console.log(arr1 === arr2); // -> false
Để kiểm tra xem hai object riêng biệt có nội dung giống nhau ko, cách đơn giản nhất là chuyển chúng sang string rồi so sánh. Khi toán thử so sánh đc dùng với kiểu dữ liệu nguyên thủy, chúng đơn là check xem value có giống nhau hay ko.
var arr1str = JSON.stringify(arr1);
var arr2str = JSON.stringify(arr2);
console.log(arr1str === arr2str); // true
Hay một cách khác là lặp từng trường của object rồi so sánh xem chúng có giống nhau hay ko.
Nguồn : https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
All rights reserved