将对象按引用传递给函数时出现不符合预期的行为
搞懂JavaScript中对象的“引用传递”误区
兄弟,我太懂你这种困惑了!刚啃JS对象引用这块的时候,很容易被“按引用传递”这个说法带偏,咱们一步步拆解你的问题,把这个坑给踩平。
先看你正常工作的第一段代码
你这段代码逻辑完全没问题,先贴出来再唠:
var c = { why: 'older' }; var d; d = c; // 这里是把c存储的对象引用值复制给d function changeGreeting(obj) { obj.why = 'newer' ; // 修改的是引用指向的对象本身 } changeGreeting(d) console.log(c); // { why: 'newer' } console.log(d); // { why: 'newer' }
为啥它能成?因为d = c并不是让d和c变成“同一个东西”,而是把c里存的对象引用值(可以理解为指向内存中对象的地址)复制了一份给d。现在c和d是两个独立的变量,但它们都指向内存里同一个对象。
当你在函数里修改obj.why时,你是顺着obj里的引用找到那个共享的对象,直接修改它的属性——所以不管用c还是d去访问这个对象,看到的都是更新后的结果,完全符合预期。
再聊你说的“异常孪生代码”(我猜你是踩了这个坑)
虽然你没写完那段异常代码,但根据我踩过的坑,90%的概率是你在函数里给obj重新赋值了一个新对象,比如这样:
var c = { why: 'older' }; var d; d = c; function changeGreeting(obj) { obj = { why: 'newer' }; // 这里是给形参obj重新赋值了新对象 } changeGreeting(d) console.log(c); // { why: 'older' } —— 完全没变化! console.log(d); // { why: 'older' } —— 也没变化!
为啥这次就不行了?核心点在这:JavaScript里所有函数参数都是按值传递的,对象的传递也不例外——这里传递的“值”就是对象的引用值。
当你把d传给函数的obj参数时,其实是把d里的引用值复制了一份给obj。现在d和obj是两个独立的变量,只是暂时指向同一个对象而已。但当你执行obj = { why: 'newer' }时,你是把obj这个变量里的引用值换成了新对象的引用,这和原来的d、c没有任何关系!原来的对象还是安安稳稳待在内存里,c和d依然指向它,所以输出自然还是原来的内容。
最后划几个重点,避免再踩坑
- 别再纠结“按引用传递”了,JS里没有真正的按引用传递,所有参数都是按值传递,对象传递的是引用的值。
- 如果想修改原对象,要操作对象的属性(比如
obj.xxx = ...),而不是给函数的形参变量重新赋值(obj = 新对象/新值)。 - 变量(比如c、d、函数里的obj)都是独立的容器,它们只是存储了指向对象的“地址”,修改容器里的“地址”不会影响其他容器里的“地址”。
内容的提问来源于stack exchange,提问作者user9441213
相关产品推荐
相关产品推荐

