Tong Hoang Vu
Tong Hoang Vu's blog

Tong Hoang Vu's blog

Pass by reference, vậy có mấy reference?

Pass by reference, vậy có mấy reference?

Điều bạn chưa biết về pass by reference

Tong Hoang Vu's photo
Tong Hoang Vu
·Jun 27, 2021·

3 min read

Subscribe to my newsletter and never miss my upcoming articles

Đây là một chủ đề thoạt nhìn có vẻ đơn giản, do bạn nào học lập trình cũng đều biết (chưa biết thì nên xem lại nha). Tuy nhiên nó không đơn giản như vậy, và nó hay đến mức mình phải viết ra một bài như thế này.

Cụ thể hôm nọ mình có tham gia thảo luận một câu hỏi trên Dạy nhau học. Tính mình thích tìm tòi nên lao đầu vô code demo thử. Và hóa ra, chính từ "pass by reference" làm mình nhầm lẫn về bản chất của nó.

Ai cũng biết pass by reference

const john = {
    name: 'John',
    age: 20
}

function test(person) {
    person.name = 'Noname';
}
test(john);

console.log(john);

Ai cũng biết khi truyền đối số theo dạng pass by reference cho function thì đối số đó có khả năng bị thay đổi sau khi ra khỏi function.

Tuy nhiên, như thế nào là thay đổi? Đơn giản nhất như đoạn code trên, truyền object vào function, thì field name bị thay đổi. Đúng, đó cũng là một dạng thay đổi, nhưng nếu toàn bộ object bị thay thế thì sao?

Thay đổi reference

Với trường hợp function thay đổi toàn bộ object, nghĩa là tham chiếu tới một object khác, thì sẽ thế nào?

const john = {
    name: 'John',
    age: 20
}

function test(person) {
    person = {
        name: 'Mike',
        age: 21
    }
}
test(john);

console.log(john);

Có thể bạn đoán được rồi, nhưng thừa nhận đi, bạn chưa bao giờ nghĩ đến điều này trước đây (nếu có, xin chúc mừng, bạn thật pro).

Kết quả đoạn code trên vẫn in ra John như cũ. Điều đó chứng tỏ.

Thay đổi reference của tham số bên trong function không ảnh hưởng tới reference bên ngoài.

Mình đã viết lại đoạn code trên cho những ngôn ngữ khác như Java, Python,... và đều có kết quả tương tự:

  • Thay đổi field của object bên trong function, object bên ngoài bị thay đổi
  • Thay đổi reference của object bên trong function (trỏ tới object mới), object bên ngoài vẫn giữ nguyên

Từ những kết quả trên, có thể đưa ra kết luận như sau. Khi một object được pass by reference thì chỉ có một vùng nhớ, nhưng lại có tới hai reference được tạo ra. Một reference của object ở bên ngoài function, một reference copy chính là tham số của function.

Quan điểm của Java

Java có quan điểm khá hay về vụ này, mình xin nêu ra như sau.

Java is always pass by value.

Mình thích cách Java phân tách rõ hai phần của object: reference (tham chiếu) và vùng nhớ trỏ tới. Khi truyền object vào function, chỉ có reference được truyền làm đối số. Như vậy, cách reference được truyền giống y như primitive types, nên gom lại chỉ còn pass by value.

Do đó, có thể dễ dàng hiểu được bản chất của pass by reference ở cả hai trường hợp trên mà không bị nhầm lẫn gì:

  • Trường hợp pass object nhưng thay đổi field: do có 2 tham chiếu nhưng chỉ 1 vùng nhớ, nên object bị thay đổi là đương nhiên.
  • Trường hợp pass object nhưng tham chiếu bị trỏ tới object khác: chỉ có bản sao tham chiếu bị trỏ tới object mới, tham chiếu gốc bên ngoài không bị ảnh hưởng.

Do nói như trên thì dài dòng quá, nên người ta mới tạo ra một thuật ngữ gọn hơn là.

Pass reference by value.

Bạn nào không tin hoặc muốn biết thêm chi tiết cứ search thử từ trên trong ngoặc kép nhé.


Bài viết này hơi nặng kĩ thuật một tí, có thể nhiều bạn đọc qua cũng không hiểu gì. Mình biết điều đó, tuy vậy mình vẫn viết ra đây để chia sẻ cho mọi người. Nếu bạn hiểu, nhớ comment xuống dưới cho mình biết nhé. Cảm ơn ❤

 
Share this