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

JavaScript中抛出错误时如何在控制台打印格式化可展开对象?

问题背景

console.error()(或console.log())支持可变长度参数列表,可以友好打印对象、数组的结构化内容,示例代码如下:

const spaghettio = {sauce: 'arrabiata', cheese: 'gorgonzola'}
console.log(`Uh oh,`, spaghettio)

这种方式打印的对象支持在控制台展开查看所有键值,调试大对象时非常方便:
console.log()格式化输出的对象

但如果要抛出正式的Error对象,没法直接复用这个打印能力,常见的写法有两种:

// 写法1:先打日志再抛错,代码重复,且错误消息里对象格式化失效
console.error(`Uh oh`, spaghettio)
throw new Error(`Uh oh: ${spaghettio}`)

// 写法2:用JSON序列化,没法展示函数、undefined值,遇到循环引用会报错,也不支持控制台展开
throw new Error(`Uh oh: ${JSON.stringify(spaghettio)}`)

两种写法都有问题:要么代码重复,要么格式化效果远不如原生console的展示效果。

最优实现方案

直接封装统一的格式化错误抛出工具函数,一次实现两个目标:复用console原生的友好格式化打印能力,同时抛出标准Error对象,避免重复代码。

基础通用版(全环境兼容)

这个版本完全保留console原生的对象打印体验,同时把结构化调试数据挂在错误实例上,方便上层捕获时使用:

/**
 * 抛出标准错误,同时在控制台输出可展开的友好格式化调试内容
 * @param {string} message 错误提示文本
 * @param  {...any} debugParams 需要附加展示的任意类型调试参数
 */
function throwFormattedError(message, ...debugParams) {
  // 直接复用console.error的可变参数逻辑,打印和原生体验完全一致的可展开内容
  console.error(message, ...debugParams)
  // 抛出标准错误,同时把调试数据挂在标准cause字段上(ES2022原生支持)
  throw new Error(message, { cause: debugParams })
}

// 调用示例
const spaghettio = {sauce: 'arrabiata', cheese: 'gorgonzola'}
throwFormattedError('Uh oh', spaghettio)

这个方案的优势:

  • 零重复代码:全局只需要封装一次,所有需要抛错带对象调试的场景直接调用即可
  • 格式化效果拉满:控制台打印的内容和直接写console.error完全一致,支持嵌套对象展开、查看属性类型、原型链,不会出现[object Object],遇到循环引用、函数、undefined值也不会序列化失败
  • 符合标准规范:用ES原生支持的cause字段存调试数据,上层catch到错误后可以直接通过err.cause拿到结构化的原始数据,不用反序列化字符串,做日志上报、二次调试都很方便

增强版:让错误消息字符串也带格式化内容

如果希望错误本身的message字符串里也能看到对象内容(比如日志上报时不依赖控制台交互),可以针对运行环境加字符串格式化逻辑:

Node.js环境

Node内置了util.inspect方法,可以把对象转成和控制台展示几乎一致的格式化字符串,支持设置递归深度、展示隐藏属性:

import util from 'node:util'

function throwFormattedError(message, ...debugParams) {
  console.error(message, ...debugParams)
  const formattedDebugContent = debugParams
    .map(item => typeof item === 'object' && item !== null 
      ? util.inspect(item, { depth: null }) 
      : String(item)
    )
    .join(' ')
  throw new Error(`${message} ${formattedDebugContent}`, { cause: debugParams })
}

浏览器环境

浏览器没有内置util.inspect,可以用带缩进的JSON.stringify做基础字符串格式化,兜底处理循环引用的场景:

function stringifyDebugValue(value) {
  if (typeof value !== 'object' || value === null) return String(value)
  try {
    return JSON.stringify(value, null, 2)
  } catch (err) {
    return String(value)
  }
}

function throwFormattedError(message, ...debugParams) {
  console.error(message, ...debugParams)
  const formattedDebugContent = debugParams.map(stringifyDebugValue).join(' ')
  throw new Error(`${message} ${formattedDebugContent}`, { cause: debugParams })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:36:21