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

JavaScript forEach遍历对象数组时为何能直接修改原数组元素?

问题描述

你定义了如下存储人员信息的对象数组:

const people = [
   {
     name: "John",
     dateOfBirth: 1990,
     dateOfDeath: 2020
   },
   {
     name: "Jane",
     dateOfBirth: 1970,
     dateOfDeath: 2019,
   },
   {
    name: "Micheal",
    dateOfBirth: 2002,
   }
 ]

需求为遍历整个数组,为所有不存在dateOfDeath属性(即仍然在世)的人员对象,将其dateOfDeath属性设置为当前年份。你编写了如下代码实现需求:

people.forEach ( element => {
   if(!("dateOfDeath" in element)) 
        element.dateOfDeath = (new Date()).getFullYear();
});

你的核心疑问:

为什么上述代码可以正常生效?回调箭头函数是如何访问并修改数组内元素的?按照常规理解,element作为回调函数的参数属于函数内的局部变量,对该变量的修改理应不会影响原数组中的元素,为什么实际运行时却修改了原数组的对应对象?


解答

这是JavaScript引用类型的基础特性,核心原因是你混淆了「修改变量本身的绑定」和「修改变量指向的对象属性」两种完全不同的操作:

  • JavaScript中对象属于引用类型,数组存储对象类型值时,存的不是对象的完整内容,而是指向堆内存中实际对象的引用地址(可以理解为指向对象存储位置的指针)。
  • forEach方法遍历到对应数组项时,会把数组当前索引位存储的引用地址拷贝一份,传给回调函数的形参element。此时函数内的局部变量element,和原数组对应位置存储的引用,指向堆内存里同一个对象实例。
  • 如果你在回调中直接给element变量重新赋值,比如写element = {name: "test"},这只是改变了局部变量element存储的引用指向,让它指向一个全新的对象,这种操作完全不会改动原数组中存储的引用地址,原数组不会受到任何影响。
  • 但你代码中执行的是element.dateOfDeath = xxx,这个操作根本没有修改element变量本身存储的引用地址,而是顺着这个地址找到堆内存里的原对象,直接给这个对象新增/修改属性。这个对象本身就是原数组引用的对象,修改结果自然会直接同步反映到原数组上。

补充说明:你最初写的示例代码中new date()存在大小写错误,Date构造函数首字母必须大写才能正常运行,可生效的正确写法为new Date().getFullYear()


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:36:15