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

Node.js中如何复制任意对象的所有自有属性?

问题分析与解决方案

你的推测完全正确:Error实例的message、stack等核心属性属于自身非枚举属性,而Object.assign()和对象展开语法({...obj})仅会复制对象的可枚举自身属性,这就是你复制后拿不到这些属性的原因。同时浏览器控制台对Error实例有特殊格式化逻辑,直接打印Error时会显示这些非枚举属性,但打印复制后的普通对象就不会。

通用解决方案(支持所有对象,包括Error)

如果想要复制对象的所有自身属性(含非枚举),同时可选保留原型链,可通过以下两种方式实现:

1. 保留原型链(保持instanceof判定)

这个方法会创建一个与原对象原型一致的新对象,并复制所有自身属性(包括非枚举):

function copyWithAllProperties(obj) {
  // 创建继承原对象原型的新实例
  const copy = Object.create(Object.getPrototypeOf(obj));
  // 获取原对象所有自身属性的描述符(含非枚举)
  const propDescriptors = Object.getOwnPropertyDescriptors(obj);
  // 将所有属性定义到新对象上
  Object.defineProperties(copy, propDescriptors);
  return copy;
}

测试示例:

const err = new Error('foo');
err.bar = 'bar';

const copiedErr = copyWithAllProperties(err);
console.log(copiedErr); // 会显示message、stack、bar属性
console.log(copiedErr instanceof Error); // true
console.log(copiedErr.message); // 'foo'
console.log(copiedErr.stack); // 完整栈信息
console.log(copiedErr.bar); // 'bar'

2. 仅复制属性(转为普通对象,不保留原型)

如果不需要保留原对象的原型链,只需要把所有自身属性(含非枚举)复制到一个普通对象中:

function extractAllOwnProperties(obj) {
  const propDescriptors = Object.getOwnPropertyDescriptors(obj);
  return Object.defineProperties({}, propDescriptors);
}

测试示例:

const plainObj = extractAllOwnProperties(new Error('foo'));
console.log(plainObj); // { message: 'foo', stack: '...' }
console.log(plainObj instanceof Error); // false

说明

  • 以上方法是通用的,不仅适用于Error,对任何包含非枚举自身属性的对象(比如自定义类实例、Date实例等)都有效。
  • 上述实现为浅拷贝,如果需要深层复制非枚举属性,可在函数中递归处理嵌套对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:12:39