let a = {
name: 'aa'
};
function fun1(a) {
a = []; // 这里创建了一个新的局部变量a,它是一个空数组
// a.name = "芜湖"
}
fun1(a); // 调用fun1,传入a的引用副本
console.log(a); // 输出:{ name: 'aa' }
在 JavaScript 中,当你将对象赋值给一个变量,比如 a
,然后传递这个变量给一个函数,如 fun1
,你实际上是传递了一个引用的副本。这意味着原始的 a
和函数内的 a
都指向同一个内存地址。
然而,当你在 fun1
函数内部将 a
赋值为一个新数组时,你并没有改变原始对象 a
的引用,而是在函数作用域内创建了一个新的局部变量 a
,这个局部变量 a
与函数外部的 a
是不同的。
let a = {
name: 'aa'
};
function fun1(a) {
a = []; // 这里创建了一个新的局部变量a,它是一个空数组
}
fun1(a); // 调用fun1,传入a的引用副本
console.log(a); // 输出:{ name: 'aa' }
执行 fun1(a)
后,控制台将输出 { name: 'aa' }
,因为原始的 a
对象没有被修改。只有当 fun1
函数内部对传入的参数进行修改(比如修改它的属性),原始的 a
对象才会受到影响。例如:
function fun1(a) {
a.name = 'bb'; // 修改对象的属性
}
fun1(a);
console.log(a); // 输出:{ name: 'bb' }
在这个修改后的 fun1
函数中,我们修改了传入对象的 name
属性,这将影响原始的 a
对象,因此控制台将输出 { name: 'bb' }
。
总结 —— javascript 的函数传值
在 JavaScript 中,函数参数的传递方式取决于参数的类型。JavaScript 将数据类型分为两种:原始类型(Primitive types)和引用类型(Reference types)。
-
原始类型(Primitive types):包括
string
、number
、boolean
、null
、undefined
和symbol
。当这些类型的值作为参数传递给函数时,它们是按值传递的。这意味着函数接收到的是原始值的一个副本,函数内部对参数的修改不会影响到原始值。 -
引用类型(Reference types):包括
object
(例如数组array
、函数function
、日期date
等),以及array
本身。当引用类型的值作为参数传递给函数时,实际上是按引用传递的。然而,这里的“引用”指的是对内存地址的引用,而不是实际的对象本身。也就是说,函数接收到的是指向原始对象的引用的副本,而不是对象的一个副本。简单来说就是指向同一个地址(引用),如果让它指向新的地址,对原来的引用类型数据不影响,但是如果在这个地址上做出改变,对原始数据有影响, 可以参考上面例子理解
这意味着,如果你在函数内部修改了对象的属性或内容,这些修改会影响到原始对象,因为函数内部的引用和外部的引用都指向同一个内存地址。但是,如果你在函数内部将参数赋值为一个全新的对象,这将创建一个新的局部变量,它不会影响到原始对象。
举个例子来说明这两种情况:
let num = 5;
function changePrimitive(num) {
num = 10; // 函数内部修改了参数的值,但原始值不变
}
function changeReference(obj) {
obj = { name: 'new object' }; // 函数内部创建了一个新的对象,原始对象不变
}
changePrimitive(num);
console.log(num); // 输出:5
let obj = { name: 'original object' };
changeReference(obj);
console.log(obj); // 输出:{ name: 'original object' }
在 changePrimitive
函数中,尽管函数内部修改了 num
的值,但原始的 num
变量不受影响。而在 changeReference
函数中,尽管函数内部尝试修改 obj
,但由于我们创建了一个新的对象并赋值给 obj
参数,原始的 obj
对象也不受影响。这是因为 obj
参数在函数内部被重新赋值为一个指向新对象的引用,但这个新的引用并没有影响到原始的 obj
变量。