Javascript: Immutability là gì?

Javascript: Immutability là gì?

Chào các men. Một ngày mới tốt lành chứ? Hôm nay chúng ta quay lại với Javascript nhé. Trước khi bắt đầu tìm hiểu về Immutability(sự bất biến), chúng ta nói qua một chút thế nào là mutation(sự biến đổi) nhé!

Mutation

Mutation là tất cả những cách thức mà chúng ta tác động lên một đối tượng làm thay đổi dữ liệu ban đầu của nó. Ví dụ:

let a = 1;
a = 2;
console.log(a)//2
//In the above case, we are mutating(transforming) the value of the variable a.

Pass by Value and Pass by Reference

let a = 5;
let b = a;

console.log(a); // 5
console.log(b); // 5

a = 15;
console.log(a); // 15
console.log(b); // 5

Chúng ta có hai biến ab. Sau đó, chúng ta thay đổi giá trị của a bằng 15. Như thế, chúng ta đã mutate dữ liệu của a. Nhưng dữ liệu của b vẫn như ban đầu. Trong javascript, chúng ta gọi đây là Pass by Value.

let object1 = {name: 'sai'};
let object2 = object1;

console.log(object1); // {name: 'sai'}
console.log(object2); // {name: 'sai'}

object1.name = 'charan';

console.log(object1); // {name: 'charan'}
console.log(object2); // {name: 'charan'} WHAAAAAT?

Chúng ta có hai object là object1object2. Object2 được gán bằng object1, trong javascript khi gán một object bằng một object thì chúng ta đang trỏ vùng nhớ của object2 tới vùng nhớ của object1. Cho nên trên thực tế, cả hai object đang reference với nhau hay là Pass by Reference. Khi chúng ta đổi property “name” của object1, do object2 đang trỏ cùng vùng nhớ với object1 nên cả hai cùng thay đổi. Ở đoạn code trên bạn sẽ thấy, giá trị của hai object bây giờ là bằng nhau.

Chúng ta cũng có thể thấy Pass by Reference xảy ra với Array:

let arr = [1,2,3,4,5];
let newArr = arr;

console.log(arr); // [1,2,3,4,5]
console.log(newArr); // [1,2,3,4,5]

arr.push(6);

console.log(arr); // [1,2,3,4,5,6]
console.log(newArr); // [1,2,3,4,5,6] WHAAAAAT?

Khi push một phần tử vào mảng arr, thì cũng  đồng nghĩa với bạn đang push một phần tử đó vào mảng newArr. Vì cả arrnewArr đều trỏ về cùng một vùng nhớ.

Kết luận ở đây, cả Object và Array trong javascript đều là Pass by Reference.

Hậu quả của Pass by Reference

Việc không tìm hiểu kỹ cách thức hoạt động của Object và Array trong javascript gây ra khá nhiều khó khăn khi bạn truy nguồn gốc thay đổi của các biến. Giả sử, bạn có một Array và rồi bạn sử dụng nó làm input cho nhiều function thì nó sẽ bị thay đổi nhiều nơi, bạn khó có thể truy được nguồn gốc của sự thay đổi. Qua mỗi hàm, thì biến Array của bạn lại bị thay đổi(mutate), và qua hàm khác lại bị thay đổi. Thử tường tượng, dữ liệu đó quan trọng thì chuyện gì sẽ xảy ra. Nó bị thay đổi khắp nơi, và khi bị sai giá trị bạn cũng khó có thể biết hàm nào, khu vực nào đã làm thay đổi biến của bạn.

Để giải quyết vấn đề mutation lung tung trong javascript đối với Object và Array, cộng đồng developer đã đề nghị nhiều cách khác nhau. Trong đó, nổi bật hơn hết là kiến trúc Redux, thư viện Immutable.js. Nhưng có cách nào không dùng thư viện mà có thể quản lý dễ dàng được Pass by Reference không? Một tin vui là có. Chúng ta có thể sử dụng một số cú pháp của ES6 để những biến của chúng ta được Immutablity.

Object.assign

let object1 = {name: 'sai'};
let object2 = Object.assign({}, object1, {name: 'charan'});

console.log(object1); // {name: 'sai'}
console.log(object2); // {name: 'charan'}

object1.name = 'batman';

console.log(object1); // {name: 'batman'}
console.log(object2); // {name: 'charan'}

Bạn có thể thấy cùng ví dụ như trên nhưng object 1 và object 2 không reference nhau nữa.

Spread Operator (…)

Chúng ta có thể cùng spread(…) như sau:

let object1 = {name: 'sai'};
let object2 = {...object1, name: 'charan'};

console.log(object1); // {name: 'sai'}
console.log(object2); // {name: 'charan'}

object1.name = 'batman';

console.log(object1); // {name: 'batman'}
console.log(object2); // {name: 'charan'}

Hay với Array:

let arr = [1,2,3,4,5];
let newArr = [...arr, 6];

console.log(arr); // [1,2,3,4,5]
console.log(newArr); // [1,2,3,4,5,6]

arr.push(11);

console.log(arr); // [1,2,3,4,5,11]
console.log(newArr); // [1,2,3,4,5,6]

Việc hiểu được và quản lý tốt Mutation và Immutability sẽ giúp chúng ta dễ maintain code hơn, dễ debug hơn. Chúc các chế thành công.

Leave a Comment