JavaScript的参数传递机制经常令人困惑,常常被争论为按值传递或按引用传递。实际上,情况更为细致:JavaScript采用了一种结合了这两种机制的机制,完全取决于所涉及的数据类型。
目录
理解基本类型的按值传递
JavaScript的基本数据类型——number
、string
、boolean
、null
、undefined
、bigint
和symbol
——使用按值传递的方式运作。当基本类型传递给函数时,会创建一个其值的副本并传递。函数内部的修改只会影响此副本,而不会影响原始变量。
let x = 10;
function changeValue(y) {
y = 20;
}
changeValue(x);
console.log(x); // 输出:10
在这个例子中,在changeValue
内部更改y
不会改变原始的x
。
理解对象的按引用传递
JavaScript中的对象(包括数组和函数)的行为有所不同。当对象传递给函数时,传递的是一个引用——指向对象内存位置的指针。因此,对对象属性在函数*内部*所做的任何修改都会直接影响原始对象。
let myArray = [1, 2, 3];
function modifyArray(arr) {
arr.push(4);
}
modifyArray(myArray);
console.log(myArray); // 输出:[1, 2, 3, 4]
在这里,myArray
被修改了,因为函数改变了对象本身,而不是副本。
但是,存在一个关键的区别:在函数内部将参数重新赋值给一个*新的*对象*不会*修改原始对象。
let myObject = { a: 1 };
function reassignObject(obj) {
obj = { a: 2 }; // 赋值一个新对象
}
reassignObject(myObject);
console.log(myObject); // 输出:{ a: 1 }
在reassignObject
内部,obj
指向一个不同的对象;原始的myObject
保持不变。
调和JavaScript中的按值传递和按引用传递
JavaScript的参数传递并非严格地只有一种方式。它是一个依赖于上下文的系统:
- 基本类型:按值传递。传递值的副本;内部更改不会影响原始值。
- 对象:按引用传递。传递对对象的引用;对对象属性的更改会影响原始对象。在函数内部将参数重新赋值给新对象不会影响原始对象。
掌握这种区别对于编写健壮且可预测的JavaScript代码至关重要。其行为完全取决于您是使用基本类型还是对象。