01/10/2018, 17:32

Lưu ý khi truyền đối số cho hàm trong JavaScript

Tất cả các tham số của hàm trong ECMAScript thì được truyền theo kiểu tham trị. Điều này có nghĩa là một giá trị bên ngoài của hàm được copy bỏ vào đối số bên trong hàm thì giống như cách một giá trị được copy từ một biến này sang biến khác. Nếu giá trị là kiểu nguyên thủy thì nó copy giống như ...

Tất cả các tham số của hàm trong ECMAScript thì được truyền theo kiểu tham trị. Điều này có nghĩa là một giá trị bên ngoài của hàm được copy bỏ vào đối số bên trong hàm thì giống như cách một giá trị được copy từ một biến này sang biến khác. Nếu giá trị là kiểu nguyên thủy thì nó copy giống như kiểu nguyên thủy làm, nhưng nếu giá trị là kiểu tham trị thì nó copy giống như kiểu tham chiếu làm. Đây là điểm thường hay gây nhầm lẫn cho chúng ta bởi vì các biến được truy xuất bằng tham trị và tham chiếu nhưng các đối số thì chỉ được truyền bằng tham chiếu. Tại sao?

Khi một đối số được truyền theo kiểu tham trị, một giá trị được copy vào biến cục bộ. Khi một đối số được truyền theo kiểu tham trị, giá trị cất giữ vị trí của đối tượng trong bộ nhớ được cất giữ trong biến cục bộ, điều này có nghĩa là những thay đổi của biến cục bộ là ảnh hưởng đến bên ngoài hàm. Ví dụ như:

function addTen(num) {
    num += 10;
    return num;
}
                   
var count = 20;
var result = addTen(count);
alert(count);    //20 - không thay đổi
alert(result);   //30 

Chúng ta có hàm addTen() có một đối số là num. Khi hàm được gọi, biến count được truyền vào như là đối số của hàm. Biến này có giá trị là 20 và nó được copy bỏ vào đối số num để sử dụng bên trong hàm addTen(). Bên trong hàm, đối số num thay đổi giá trị của nó bằng cách cộng thêm 10. Tuy nhiên, điều này không làm thay đổi giá trị gốc của biến count tồn tại bên ngoài hàm. Đối số num và biến count không làm ảnh hưởng lẫn nhau. Nếu mà đối số num truyền theo kiểu tham chiếu thì giá trị của biến count sẽ thay đổi thành 30 bở sự thay đổi bên trong hàm. Ví dụ cho truyền theo tham chiếu như sau:

function setName(obj) {
    obj.name = "Goc kinh nghiem";
}
                   
var person = new Object();
setName(person);
alert(person.name);    //"Goc kinh nghiem" 

Trong đoạn mã trên, một đối tượng được cất giữ trong một biến person. Đối tượng này khi đó truyền vào phương thức setName() và đối tượng person được copy bỏ vào đối tượng obj. Bên trong hàm, obj và person cùng trỏ đến cùng đối tượng. Kết quả là obj thì đang truy cập đến một đối tượng bằng tham trị, mặc dù được truyền vô hàm theo tham trị. Khi mà thuộc tính name được set cho obj bên trong hàm, điều này cũng làm ảnh hưởng bên ngoài hàm bởi vì đối tượng nó trỏ tới tồn tại trong heap

Nhìn vào ví dụ trên, chúng ta sẽ cho là đây là tham chiếu chứ không phải tham trị vì chúng ta thay đổi cục bộ mà ảnh hưởng đến toàn cục. Để chứng minh nó là tham trị chúng ta hãy nhìn vào ví dụ sau:

function setName(obj) {
    obj.name = "Goc kinh nghiem";
    obj = new Object();
    obj.name = "Hoc JavaScript";
}
                   
var person = new Object();
setName(person);
alert(person.name);    //"Goc kinh nghiem";

Mặc dù chúng ta đã tạo một đối tượng với tên mới nhưng giá trị của thuộc tính name vẫn không thay đổi. Nếu person được truyền theo kiểu tham chiếu thì sẽ phải in ra là chuỗi “Hoc JavaScript” chứ không phải là “Goc Kinh Nghiem”


0