拷贝对象时动态增删字段的关键是不修改原对象,而是通过展开运算符、Object.keys()或Object.entries()在拷贝过程中筛选、添加或覆盖属性;需区分浅拷贝与深拷贝场景。

拷贝对象时动态增删字段,关键在于不直接修改原对象,而是在拷贝过程中按需筛选、添加或覆盖属性。常用且安全的方式是结合展开运算符(...)、Object.keys() 或 Object.entries() 手动控制字段。
用展开运算符 + 显式字段控制增删
适合字段数量少、逻辑明确的场景。删除字段时“排除”,新增字段时“覆盖”或“追加”。
- 删除某个字段:
{...obj, fieldToExclude: undefined}不够稳妥,推荐解构排除 - 更可靠写法:先解构出不需要的字段,再展开剩余部分
const original = { name: 'Alice', age: 30, email: 'a@b.com' };
// 拷贝并删除 email,新增 id 和 createdAt
const copied = (({ email, ...rest }) => ({
...rest,
id: Date.now(),
createdAt: new Date().toISOString()
}))(original);
用 Object.fromEntries 动态过滤和注入
适合需要根据条件(如白名单、黑名单、类型判断)批量处理字段,灵活性高。
- 先用
Object.entries()转为键值对数组 - 用
filter()剔除不需要的字段(比如以_开头的私有字段) - 用
map()插入新字段或改写值,最后Object.fromEntries()还原为对象
const obj = { name: 'Bob', _tempId: 123, score: 95 };
const filtered = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !key.startsWith('_')) // 删除私有字段
.concat([['version', '1.2.0']]) // 动态追加
); // → { name: 'Bob', score: 95, version: '1.2.0' }
封装一个可复用的 copyWith 函数
把动态增删逻辑抽象成函数,便于多次调用,也利于统一处理 null/undefined 边界。
- 接收原对象、要删除的字段数组(
omit)、要新增/覆盖的字段对象(extend) - 内部用
Object.keys()遍历,跳过omit列表中的键,再合并extend
function copyWith(obj, { omit = [], extend = {} } = {}) {
const result = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key) && !omit.includes(key)) {
result[key] = obj[key];
}
}
return { ...result, ...extend };
}
// 使用
copyWith(user, { omit: ['password'], extend: { updatedAt: new Date() } });
注意深拷贝与引用问题
以上方法都是浅拷贝。如果对象含嵌套结构(如数组、子对象),且你希望增删的是深层字段(例如 user.profile.avatar),则需配合深拷贝工具(如 structuredClone、Lodash 的 cloneDeep)先复制,再操作。
- 浏览器环境可用
structuredClone(obj)(现代浏览器支持) - Node.js 可用
JSON.parse(JSON.stringify(obj))(仅限纯数据,不支持函数、Date、undefined 等) - 复杂场景建议用
lodash.cloneDeep+lodash.unset/lodash.set组合操作

















