关于复制javascript对象的键值对



**我试图通过执行let error={…err}来创建猫鼬发送的错误对象的副本。err是原始错误对象。现在,当我登录控制台(err.name)时,它显示";CastError";这是预期的,但是(error.name)给出了"错误";"未定义",但是当我使用error=JSON.parse(JSON.stringfy(err)),然后记录err.name和error.name时;CastError";输出,我怀疑为什么{…err}不起作用[使用时{...err}1**

使用JSON.parse()时

啊,好问题!要回答这个问题,您需要仔细阅读文档并密切关注以下小细节:

  1. MDN上对象文字文档的扩展语法提到:它将自己的可枚举属性从提供的对象复制到新对象上
  2. Error对象的ECMAScript文档表明所有属性都是不可枚举的

这两个规范的结果是,当您尝试使用排列语法克隆Error对象时,会导致一个空对象。您可以使用Object.prototype.propertyisEnumerable确认此行为

const err = new Error()
console.log(err.propertyIsEnumerable('message')) // result: false
console.log(err.propertyIsEnumerable('name')) // result: false
const error = {...err}
console.log(err) // result: {}

如果绝对需要列出对象的不可枚举属性,可以调用Object.getOwnPropertyNames,它返回对象本身的所有属性(可枚举和不可枚举)。如果需要,您可以使用Object.getPrototypeOf(obj)走上原型链并重复该操作。请注意,您可能希望过滤掉来自Object原型的属性。

下面是一个示例代码(可能有更好的方法来写…):

const getAllProps = (obj, props = []) => {
props.push(...Object.getOwnPropertyNames(obj));
const proto = Object.getPrototypeOf(obj);
if (proto !== null) return getAllProps(proto, props);
return props;
};
const objProps = getAllProps({});
const err = new Error();
const errProps = getAllProps(err).filter((prop) => !objProps.includes(prop));
console.log(errProps); // result: [ 'stack', 'name', 'message' ]

最新更新