You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript对象赋值运行机制及函数传参行为相关疑问

JS对象赋值与函数传参的内存层面原理

首先纠正一个普遍的认知误区:JS中所有的函数传参都是按值传递,不存在按引用传递的规则。传递对象类型时,传递的“值”是对象在堆内存中的地址的副本,而非原始引用本身,这是你出现预期偏差的核心原因。


第一段代码运行原理

代码如下:

function make(g: any, b: any) {
    g = b;
}


let obj = {id: 1};
let obj2 = {id: 2};

make(obj, obj2);

console.log(obj);
console.log(obj2);

内存层面执行过程:

  • 变量声明阶段:堆内存会开辟两块独立空间,分别存储{id: 1}(记为内存地址A)、{id: 2}(记为内存地址B);栈内存的变量obj存储的值为地址A,obj2存储的值为地址B。
  • 调用make(obj, obj2)阶段:函数执行上下文创建形参变量g、b,二者是完全独立于外部obj、obj2的新栈变量:
    • g被赋值为obj的值:地址A的副本
    • b被赋值为obj2的值:地址B的副本
  • 执行g = b时:仅修改了形参g存储的地址值,从A改为B,全程没有修改外部obj的存储值,也没有修改堆内存中的原有数据。
  • 函数执行结束后,形参g、b随执行上下文销毁,外部obj、obj2的指向没有任何变化,最终打印结果分别为{id: 1}、{id: 2},符合逻辑。

第二段代码运行原理

代码如下:

function make(g: any) {
    g = {};
}

let obj = {id: 1};
make(obj);
console.log(obj);

内存层面执行过程:

  • 变量声明阶段:堆内存开辟空间存储{id: 1}(地址A),栈变量obj存储地址A。
  • 调用make(obj)阶段:函数执行上下文创建形参g,赋值为地址A的副本,和外部obj是独立的两个栈变量。
  • 执行g = {}时:堆内存新开辟空间存储空对象(地址C),将形参g的存储值修改为地址C,这个修改完全不影响外部obj的存储值,obj仍然指向地址A。
  • 函数执行结束后形参销毁,最终打印obj结果为{id: 1},和第一段代码的逻辑完全一致,不存在异常。

补充:什么时候修改会影响外部对象?

只有当你没有修改形参存储的地址值,而是直接修改地址指向的堆内存内容时,外部对象才会感知到变化,示例如下:

function make(g: any) {
    g.id = 3; // 直接修改地址指向的堆内存内容
}
let obj = {id: 1};
make(obj);
console.log(obj); // 打印结果为 {id: 3}

内容的提问来源于stack exchange,提问作者user15361861

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 01:33:02