【问题标题】:How do I copy Javascript Error without reference?如何在没有参考的情况下复制 Javascript 错误?
【发布时间】:2026-01-15 09:35:01
【问题描述】:

我想复制 Javascript Error 而不参考。

例子:

const error1 = new Error('error1');
const error2 = error1;

error2.message = 'error2';

console.log(error1);
console.log(error2);

输出:

Error: error2
    at evalmachine.<anonymous>:1:16
    at Script.runInContext (vm.js:133:20)
    at Object.runInContext (vm.js:311:6)
    at evaluate (/run_dir/repl.js:133:14)
    at ReadStream.<anonymous> (/run_dir/repl.js:116:5)
    at ReadStream.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)
    at lazyFs.read (internal/fs/streams.js:181:12)

Error: error2
    at evalmachine.<anonymous>:1:16
    at Script.runInContext (vm.js:133:20)
    at Object.runInContext (vm.js:311:6)
    at evaluate (/run_dir/repl.js:133:14)
    at ReadStream.<anonymous> (/run_dir/repl.js:116:5)
    at ReadStream.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)
    at lazyFs.read (internal/fs/streams.js:181:12)

当我更改error2 时,error1 也会更改。然后我尝试了lodashclone 功能。但不幸的是,它返回的是一个对象,而不是 Error 的实例。有没有办法让我可以复制 Error 而不引用并返回 instanceof Error 而不更改 stack 或其他默认属性?

【问题讨论】:

  • 你想用这个来完成什么?
  • 我有几个函数在它们的参数中发送错误,我不希望原来的Error 被打断。所以我想为每个函数复制一个Error。就像温斯顿的formats
  • 这是因为当您分配它时,您正在创建一个引用,请尝试仅分配您感兴趣的成员并包装在 String() 中。
  • 但是为什么任何处理程序会变异错误对象?
  • winston 库将info 参数设为instanceof Error,如果您将Error 输入到他们的记录器。我需要更改info 参数中的一些属性,因为winston 将他们的消息存储在info[Symbol('message')]

标签: javascript object clone object-reference


【解决方案1】:

您可以尝试手动输入一些重要的属性:

const error1 = new Error('error1');
const error2 = new error1.constructor(error1.message);

if (error1.stack) {
  error2.stack = error1.stack;
}

if (error1.code) {
  error2.code = error1.code;
}

if (error1.errno) {
  error2.errno = error1.errno;
}

if (error1.syscall) {
  error2.syscall = error1.syscall;
}

error2.message = 'error2';

console.log(error1);
console.log(error2);

【讨论】:

    【解决方案2】:

    如果您坚持对错误进行单独的副本,我认为您最好的选择是创建一个新错误并复制您要保留的属性:

    function copyError(err, newMessage) {
        var newErr = new Error(newMessage);
    
        newErr.stack = err.stack;
        // copy other properties
    }
    
    var newErr = copyError(e, "New message");
    

    但是,我不认为这是一个很好的方法。

    另一种选择是做类似 .NET 所做的事情 - 创建一个新错误并将原始错误放在该错误的属性上:

    var newErr = new Error("New message");
    newErr.innerError = originalError;
    

    这里的缺点是检查这些错误的任何东西都需要检查.innerError 属性的存在并相应地使用它。

    【讨论】:

      最近更新 更多