JavaScript传参的本质——值传递

JavaScript传参的本质——值传递

前言

先说结论:Javascript传参都是值传递。只是因为不同的内存分配机制带来了不同的访问机制,基本数据类型值都存放在栈内存中,引用类型的值都存放在堆内存中,并在栈内存中用指针变量存放了对应对象的地址。当传参的时候也就是直接把栈内存的值复制一份而已,只是复制的值对原始值来说就直接是原始值,但是对对象指针来说就是其地址。

回顾JavaScript数据类型

JavaScript笔记(1) - 3的4次方 - 博客园

JavaScript 中的数据类型分为两大类:

  1. 基本数据类型(值类型):
    • NumberStringBooleanNullUndefinedSymbolBigInt
    • 直接存储在栈内存中,值不可变
    • 不可以动态得添加属性:
  2. 引用数据类型
    • 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函数执行后
image image image
posted @ 2025-10-30 14:46  3的4次方  阅读(4)  评论(0)    收藏  举报