JavaScript传参的本质——值传递
JavaScript传参的本质——值传递
前言
先说结论:Javascript传参都是值传递。只是因为不同的内存分配机制带来了不同的访问机制,基本数据类型值都存放在栈内存中,引用类型的值都存放在堆内存中,并在栈内存中用指针变量存放了对应对象的地址。当传参的时候也就是直接把栈内存的值复制一份而已,只是复制的值对原始值来说就直接是原始值,但是对对象指针来说就是其地址。
回顾JavaScript数据类型
JavaScript 中的数据类型分为两大类:
- 基本数据类型(值类型):
Number、String、Boolean、Null、Undefined、Symbol、BigInt- 直接存储在栈内存中,值不可变
- 不可以动态得添加属性:
- 引用数据类型:
Object(包括数组、函数、日期等)- 值存储在堆内存中,栈内存存储指向堆内存的引用地址
例子
function changeStuff(a, b, c) {
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
最终的输出结果是:
10
changed
unchanged
分析
上例中,num是基本数据类型,obj1和obj2是引用数据类型。
对于基本数据类型,其存储在栈上,JS是直接值拷贝的;对于引用数据类型,其存储在堆上,JS是拷贝其指针(obj1和obj2都是指针)。
因此传入 changeStuff 函数后,会拷贝num的值、obj1和obj2的指针到a、b和c实参:
- num的值肯定不变,因为改动的是内部的a局部变量;
- obj1的item成员变化,因为
b.item修改了b指向的堆内存值,而obj1与b指向同一块内存,导致obj1指向的对象(也是b指向的对象)被修改; - obj2的item成员不变,因为
c = {xxx}将c指向一个新创建的对象,而c本身只是obj2这个指针的拷贝,c改动了不会影响obj2的值,自然也就无法影响到obj2指向的内存的值;
调用changeStuff函数前 |
调用changeStuff函数传参时 |
调用changeStuff函数执行后 |
|---|---|---|
![]() |
![]() |
![]() |




浙公网安备 33010602011771号