JavaScript中函数返回的对象是值还是引用?如何验证两个变量指向同一对象?
JavaScript对象引用与函数返回值相关疑问解答
核心结论
- urlArgs 和函数内部的 retObj 指向完全相同的对象,属于同一引用
- 你产生误解的核心原因是混淆了「变量的作用域生命周期」和「变量指向的对象的内存生命周期」两个概念
误区解释
函数内部定义的retObj是局部变量,它的作用域确实仅限函数内部,函数执行结束后你无法再通过retObj这个变量名访问任何内容,但它指向的堆内存对象不会被自动回收:只要还有其他变量(这里就是外部的urlArgs)持有该对象的引用,JS垃圾回收机制就不会清理这个对象,对象会一直存在。
你提到的测试方法的问题
你写的urlArgs === retObj无法直接执行,因为retObj是函数内部变量,外部作用域无法访问,直接运行会抛出ReferenceError: retObj is not defined错误。
可行的验证方案
你可以通过临时变量中转的方式验证引用关系,示例代码如下:
const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); // 定义外部临时变量存储内部retObj的引用 let tempRetObj; function getUrlParams(_urlParams) { let retObj = new Object(); // 把内部retObj的引用赋值给外部临时变量 tempRetObj = retObj; _urlParams.forEach(function(value, key) { retObj[key] = value; }); return retObj; } const urlArgs = getUrlParams(urlParams); // 验证1:严格相等判断返回true,证明是同一引用 console.log(urlArgs === tempRetObj); // 验证2:修改其中一个变量指向的对象属性,另一个也会同步变化 urlArgs.testKey = "测试值"; console.log(tempRetObj.testKey); // 输出"测试值"
补充JS基础规则
JS中所有引用类型(普通对象、数组、函数、Map、Set等)的赋值、参数传递、返回值操作默认都是传递内存引用,只有基础类型(字符串、数字、布尔值、null、undefined、Symbol、BigInt)的相关操作是传递值的拷贝。
内容的提问来源于stack exchange,提问作者Jarne Kompier
相关产品推荐
相关产品推荐

