在 JavaScript 中,传递参数时有两种方式:按值传递(pass by value)和按引用传递(pass by reference),即传值与传址。
一、按值传递(传值)
基本(简单)数据类型都是传值:number、boolean、字符串、null、undefined,都存储在栈中。
按值传递意味着在函数调用时,会将参数的值复制一份,然后将这个副本传递给函数。这意味着函数内对参数的修改不会影响原始变量。
function updateValue(value) {
value = 10;
}
let num = 5,
num1 = num;
num1 = 2
updateValue(num);
console.log(num); // 输出 5,因为函数内部的修改不会影响到原始变量
console.log(num1); // 输出 2,因为同一作用域下会影响到原始变量
二、按引用传递(传址)
复杂数据类型都是传址:object、date、array等,堆:存储复杂数据类型的数据,栈:存储地址
按引用传递意味着在函数调用时,会将参数的引用(内存地址)传递给函数。这意味着函数内对参数的修改会影响到原始变量。
const user = {
name: "cyy",
};
function changeUser(user) {
user.name = "xcd";
user = {
name: "wff",
};
//user.name = "gly";
//console.log("changeUser作用域:", user.name); //gly
console.log("changeUser作用域:", user.name); //wff 此处代码和特殊情况一样
}
changeUser(user);
console.log(user.name); //xcd
// 如果将 changeUser 中的user.name = 'xcd' 注释掉 console.log(user.name); //cyy
此外,还有一种特殊情况是,当按值传递的参数是一个对象时,实际上传递的是对象的引用。这会导致函数内部可以修改对象的属性,但不能修改对象本身(即不能将参数指向一个新的对象)。
function updatePerson(person) {
person.name = 'John';
person = { name: 'Alice' }; // 这里不能修改原始对象的引用
}
let personObj = { name: 'Bob' };
updatePerson(personObj);
console.log(personObj); // 输出 { name: 'John' },因为函数内部修改了对象的属性
三、总结
- 基本数据类型是按值传递的,函数内对参数的修改不会影响原始变量。
- 对象类型是按引用传递的,函数内对参数的修改会影响原始变量,但不能将参数指向一个新的对象,对象名和参数名一样,则是重新创建了一个新的对象。