别再只会 console.log 了!这 15 个 Console 调试技巧,让你的 Debug 效率翻倍

"console.log('到这了')" "console.log('到这了 2')" "console.log('到这了 3')" "console.log('为什么不执行???')" ------ 每个程序员的日常

前言:你真的会用 console 吗?

让我猜猜你的调试方式:

javascript 复制代码
console.log(data)
console.log("data:", data)
console.log("========== 分割线 ==========")
console.log(data)
console.log("到这了")
console.log("到这了2")
console.log("为什么不进来???")

如果你中枪了,别担心,你不是一个人。

但是,console 对象其实有超过 20 个方法,而大多数人只会用 console.log

今天,我要带你解锁 console 的全部潜力。

学完这篇文章,你的调试效率至少提升 50%。


第一章:基础进阶------让 console.log 更好用

1.1 技巧一:用对象包裹变量名

这是最简单但最有用的技巧。

❌ 不好的写法:

javascript 复制代码
const userName = "张三"
const userAge = 25
const userEmail = "zhangsan@example.com"

console.log(userName)
console.log(userAge)
console.log(userEmail)

// 输出:
// 张三
// 25
// zhangsan@example.com
// 问题:你根本不知道哪个是哪个!

✅ 好的写法:

javascript 复制代码
const userName = "张三"
const userAge = 25
const userEmail = "zhangsan@example.com"

console.log({ userName, userAge, userEmail })

// 输出:
// { userName: '张三', userAge: 25, userEmail: 'zhangsan@example.com' }
// 清清楚楚,一目了然!

这个技巧利用了 ES6 的对象简写语法,变量名自动成为属性名。

1.2 技巧二:给输出加上 emoji 标签

当你的控制台输出很多的时候,找到你要的那条信息就像大海捞针。

解决方案:用 emoji 做视觉标记!

javascript 复制代码
// 🔍 调试信息
console.log("🔍 正在查找用户:", userId)

// ✅ 成功信息
console.log("✅ 用户登录成功:", user.name)

// ❌ 错误信息
console.log("❌ 登录失败:", error.message)

// ⚠️ 警告信息
console.log("⚠️ 用户权限不足")

// 🚀 性能相关
console.log("🚀 API 响应时间:", responseTime, "ms")

// 📦 数据相关
console.log("📦 接收到的数据:", data)

// 🔄 状态变化
console.log("🔄 状态更新:", oldState, "->", newState)

在一堆黑白文字中,emoji 会非常显眼,让你一眼就能找到关键信息。

1.3 技巧三:使用模板字符串格式化

javascript 复制代码
const user = { name: "张三", age: 25 }
const action = "登录"
const timestamp = new Date().toLocaleTimeString()

// ❌ 拼接字符串(丑陋且难读)
console.log("用户 " + user.name + " 在 " + timestamp + " 执行了 " + action)

// ✅ 模板字符串(清晰优雅)
console.log(`[${timestamp}] 用户 ${user.name} 执行了 ${action}`)

// 输出:[14:30:25] 用户 张三 执行了 登录

1.4 技巧四:console.log 的 CSS 样式

是的,你可以给 console.log 加 CSS 样式!

javascript 复制代码
// 基础用法
console.log("%c这是红色文字", "color: red")
console.log("%c这是大号蓝色文字", "color: blue; font-size: 20px")

// 高级用法:多种样式组合
console.log(
  "%c 成功 %c 操作已完成",
  "background: #4CAF50; color: white; padding: 2px 6px; border-radius: 3px",
  "color: #4CAF50"
)

// 实用示例:创建一个漂亮的日志函数
const prettyLog = {
  success: (msg) =>
    console.log(
      `%c ✓ SUCCESS %c ${msg}`,
      "background: #4CAF50; color: white; padding: 2px 6px; border-radius: 3px; font-weight: bold",
      "color: #4CAF50"
    ),
  error: (msg) =>
    console.log(
      `%c ✗ ERROR %c ${msg}`,
      "background: #f44336; color: white; padding: 2px 6px; border-radius: 3px; font-weight: bold",
      "color: #f44336"
    ),
  warning: (msg) =>
    console.log(
      `%c ⚠ WARNING %c ${msg}`,
      "background: #ff9800; color: white; padding: 2px 6px; border-radius: 3px; font-weight: bold",
      "color: #ff9800"
    ),
  info: (msg) =>
    console.log(
      `%c ℹ INFO %c ${msg}`,
      "background: #2196F3; color: white; padding: 2px 6px; border-radius: 3px; font-weight: bold",
      "color: #2196F3"
    ),
}

// 使用
prettyLog.success("用户登录成功")
prettyLog.error("网络请求失败")
prettyLog.warning("API 即将废弃")
prettyLog.info("当前版本: 2.0.0")

第二章:数据展示------让复杂数据一目了然

2.1 技巧五:console.table() ------ 表格展示数据

这可能是最被低估的 console 方法。

当你有一个对象数组时,console.log 的输出是这样的:

javascript 复制代码
const users = [
  { id: 1, name: "张三", age: 25, city: "北京" },
  { id: 2, name: "李四", age: 30, city: "上海" },
  { id: 3, name: "王五", age: 28, city: "广州" },
]

console.log(users)
// 输出一堆难以阅读的嵌套对象...

但如果你用 console.table()

javascript 复制代码
console.table(users)

// 输出一个漂亮的表格:
// ┌─────────┬────┬────────┬─────┬────────┐
// │ (index) │ id │  name  │ age │  city  │
// ├─────────┼────┼────────┼─────┼────────┤
// │    0    │ 1  │ '张三' │ 25  │ '北京' │
// │    1    │ 2  │ '李四' │ 30  │ '上海' │
// │    2    │ 3  │ '王五' │ 28  │ '广州' │
// └─────────┴────┴────────┴─────┴────────┘

还可以只显示特定列:

javascript 复制代码
console.table(users, ["name", "city"])

// 只显示 name 和 city 列
// ┌─────────┬────────┬────────┐
// │ (index) │  name  │  city  │
// ├─────────┼────────┼────────┤
// │    0    │ '张三' │ '北京' │
// │    1    │ '李四' │ '上海' │
// │    2    │ '王五' │ '广州' │
// └─────────┴────────┴────────┘

适用场景:

  • API 返回的数据列表
  • 数据库查询结果
  • 配置项对比
  • 任何数组或对象的可视化

2.2 技巧六:console.dir() ------ 查看对象的完整结构

console.log 打印 DOM 元素时,显示的是 HTML 结构。

console.dir 打印 DOM 元素时,显示的是对象属性。

javascript 复制代码
const element = document.querySelector("#app")

console.log(element)
// 输出:<div id="app">...</div>(HTML 结构)

console.dir(element)
// 输出:div#app 的所有属性和方法(对象结构)
// 包括:className, id, innerHTML, style, onclick...

当你需要查看一个对象有哪些属性和方法时,用 console.dir

2.3 技巧七:console.dirxml() ------ 查看 XML/HTML 结构

javascript 复制代码
const element = document.querySelector("#app")

console.dirxml(element)
// 以 XML/HTML 树形结构展示元素及其子元素

第三章:分组与层级------让输出更有组织

3.1 技巧八:console.group() ------ 分组输出

当你有一堆相关的日志时,可以把它们分组:

javascript 复制代码
console.group("用户信息")
console.log("姓名: 张三")
console.log("年龄: 25")
console.log("城市: 北京")
console.groupEnd()

console.group("订单信息")
console.log("订单号: 12345")
console.log("金额: ¥99.00")
console.log("状态: 已支付")
console.groupEnd()

// 输出:
// ▼ 用户信息
//     姓名: 张三
//     年龄: 25
//     城市: 北京
// ▼ 订单信息
//     订单号: 12345
//     金额: ¥99.00
//     状态: 已支付

3.2 技巧九:console.groupCollapsed() ------ 默认折叠的分组

javascript 复制代码
console.groupCollapsed("详细调试信息(点击展开)")
console.log("这是一些详细的调试信息...")
console.log("通常不需要看,但需要时可以展开")
console.log("比如:完整的请求参数、响应数据等")
console.groupEnd()

// 输出:
// ▶ 详细调试信息(点击展开)  ← 默认是折叠的

适用场景:

  • 详细的调试信息(平时不看,出问题时展开)
  • 大量的数据输出
  • 嵌套的对象结构

3.3 技巧十:嵌套分组

javascript 复制代码
console.group("🛒 购物车")

console.group("商品列表")
console.log("iPhone 15 Pro - ¥8999")
console.log("AirPods Pro - ¥1899")
console.groupEnd()

console.group("优惠信息")
console.log("满减: -¥500")
console.log("优惠券: -¥100")
console.groupEnd()

console.log("💰 总计: ¥10298")

console.groupEnd()

// 输出:
// ▼ 🛒 购物车
//     ▼ 商品列表
//         iPhone 15 Pro - ¥8999
//         AirPods Pro - ¥1899
//     ▼ 优惠信息
//         满减: -¥500
//         优惠券: -¥100
//     💰 总计: ¥10298

第四章:性能分析------找出代码瓶颈

4.1 技巧十一:console.time() ------ 测量代码执行时间

这是性能调试的神器!

javascript 复制代码
console.time("数据处理")

// 模拟一些耗时操作
const data = []
for (let i = 0; i < 100000; i++) {
  data.push({ id: i, value: Math.random() })
}

console.timeEnd("数据处理")
// 输出:数据处理: 45.123ms

可以同时计时多个操作:

javascript 复制代码
console.time("总耗时")

console.time("获取数据")
const response = await fetch("/api/users")
const users = await response.json()
console.timeEnd("获取数据")
// 输出:获取数据: 234.56ms

console.time("处理数据")
const processedUsers = users.map((user) => ({
  ...user,
  fullName: `${user.firstName} ${user.lastName}`,
}))
console.timeEnd("处理数据")
// 输出:处理数据: 12.34ms

console.time("渲染")
renderUsers(processedUsers)
console.timeEnd("渲染")
// 输出:渲染: 89.01ms

console.timeEnd("总耗时")
// 输出:总耗时: 335.91ms

4.2 技巧十二:console.timeLog() ------ 中间计时

javascript 复制代码
console.time("多步骤操作")

await step1()
console.timeLog("多步骤操作", "步骤1完成")
// 输出:多步骤操作: 100.00ms 步骤1完成

await step2()
console.timeLog("多步骤操作", "步骤2完成")
// 输出:多步骤操作: 250.00ms 步骤2完成

await step3()
console.timeEnd("多步骤操作")
// 输出:多步骤操作: 400.00ms

4.3 技巧十三:console.count() ------ 计数器

想知道某段代码执行了多少次?

javascript 复制代码
function handleClick() {
  console.count("按钮点击")
  // 其他逻辑...
}

// 点击3次后:
// 按钮点击: 1
// 按钮点击: 2
// 按钮点击: 3

// 重置计数器
console.countReset("按钮点击")

实用场景:

javascript 复制代码
function render(component) {
  console.count(`${component} 渲染次数`)
  // 渲染逻辑...
}

// 检查组件是否有不必要的重复渲染
render("Header") // Header 渲染次数: 1
render("Header") // Header 渲染次数: 2  ← 为什么渲染了两次?
render("Header") // Header 渲染次数: 3  ← 可能有性能问题!

第五章:错误追踪------快速定位问题

5.1 技巧十四:console.trace() ------ 打印调用栈

当你想知道"这个函数是从哪里被调用的"时:

javascript 复制代码
function functionA() {
  functionB()
}

function functionB() {
  functionC()
}

function functionC() {
  console.trace("调用栈追踪")
}

functionA()

// 输出:
// 调用栈追踪
//     at functionC (script.js:10)
//     at functionB (script.js:6)
//     at functionA (script.js:2)
//     at script.js:13

这在调试复杂的回调链或事件处理时特别有用。

5.2 技巧十五:console.assert() ------ 条件断言

只有当条件为 false 时才输出:

javascript 复制代码
const user = { name: "张三", age: 25 }

// 如果条件为 true,什么都不输出
console.assert(user.name, "用户名不能为空")

// 如果条件为 false,输出错误信息
console.assert(user.age >= 18, "用户必须成年")
console.assert(user.email, "用户邮箱不能为空")
// 输出:Assertion failed: 用户邮箱不能为空

适用场景:

javascript 复制代码
function processOrder(order) {
  console.assert(order, "订单不能为空")
  console.assert(order.items?.length > 0, "订单必须包含商品")
  console.assert(order.totalAmount > 0, "订单金额必须大于0")

  // 如果所有断言都通过,继续处理...
}

第六章:实战技巧------日常开发中的最佳实践

6.1 创建一个增强版 Logger

javascript 复制代码
// logger.js - 一个实用的日志工具

const isDev = process.env.NODE_ENV === "development"

const logger = {
  // 基础日志(只在开发环境输出)
  log: (...args) => {
    if (isDev) console.log("📝", ...args)
  },

  // 信息日志
  info: (...args) => {
    if (isDev)
      console.log(
        "%c ℹ️ INFO ",
        "background: #2196F3; color: white; border-radius: 3px",
        ...args
      )
  },

  // 成功日志
  success: (...args) => {
    if (isDev)
      console.log(
        "%c ✅ SUCCESS ",
        "background: #4CAF50; color: white; border-radius: 3px",
        ...args
      )
  },

  // 警告日志
  warn: (...args) => {
    console.warn("⚠️", ...args) // 警告在生产环境也输出
  },

  // 错误日志
  error: (...args) => {
    console.error("❌", ...args) // 错误在生产环境也输出
  },

  // 分组日志
  group: (label, fn) => {
    if (!isDev) return fn()
    console.group(`📦 ${label}`)
    const result = fn()
    console.groupEnd()
    return result
  },

  // 计时日志
  time: async (label, fn) => {
    if (!isDev) return fn()
    console.time(`⏱️ ${label}`)
    const result = await fn()
    console.timeEnd(`⏱️ ${label}`)
    return result
  },

  // 表格日志
  table: (data, columns) => {
    if (isDev) console.table(data, columns)
  },
}

export default logger

// 使用示例
import logger from "./logger"

logger.info("应用启动")
logger.success("用户登录成功", { userId: 123 })
logger.warn("API 即将废弃")
logger.error("网络请求失败", error)

logger.group("用户数据", () => {
  logger.log("姓名:", user.name)
  logger.log("年龄:", user.age)
})

await logger.time("数据加载", async () => {
  return await fetchData()
})

6.2 调试 API 请求

javascript 复制代码
// 创建一个 API 调试拦截器
const debugFetch = async (url, options = {}) => {
  const requestId = Math.random().toString(36).substr(2, 9)

  console.groupCollapsed(
    `🌐 API 请求 [${requestId}] ${options.method || "GET"} ${url}`
  )

  console.log("📤 请求参数:", {
    url,
    method: options.method || "GET",
    headers: options.headers,
    body: options.body ? JSON.parse(options.body) : undefined,
  })

  console.time(`⏱️ 响应时间 [${requestId}]`)

  try {
    const response = await fetch(url, options)
    const data = await response.clone().json()

    console.timeEnd(`⏱️ 响应时间 [${requestId}]`)
    console.log("📥 响应状态:", response.status, response.statusText)
    console.log("📦 响应数据:", data)

    if (!response.ok) {
      console.error("❌ 请求失败")
    } else {
      console.log("✅ 请求成功")
    }

    console.groupEnd()
    return response
  } catch (error) {
    console.timeEnd(`⏱️ 响应时间 [${requestId}]`)
    console.error("❌ 请求异常:", error.message)
    console.groupEnd()
    throw error
  }
}

// 使用
const response = await debugFetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "张三" }),
})

6.3 调试 React 组件渲染

javascript 复制代码
// 在 React 组件中使用
function UserProfile({ userId }) {
  console.count(`UserProfile 渲染 (userId: ${userId})`)

  useEffect(() => {
    console.log("🔄 UserProfile useEffect 触发", { userId })

    return () => {
      console.log("🧹 UserProfile 清理", { userId })
    }
  }, [userId])

  console.group("📊 UserProfile 渲染详情")
  console.log("Props:", { userId })
  console.log("渲染时间:", new Date().toLocaleTimeString())
  console.groupEnd()

  return <div>...</div>
}

6.4 调试状态变化

javascript 复制代码
// 创建一个状态变化追踪器
function createStateTracker(initialState, name = "State") {
  let state = initialState

  return {
    get: () => state,
    set: (newState) => {
      console.group(`🔄 ${name} 变化`)
      console.log("旧值:", state)
      console.log("新值:", newState)
      console.trace("调用来源")
      console.groupEnd()

      state = newState
      return state
    },
  }
}

// 使用
const userState = createStateTracker({ name: "", loggedIn: false }, "UserState")

userState.set({ name: "张三", loggedIn: true })
// 输出:
// ▼ 🔄 UserState 变化
//     旧值: { name: '', loggedIn: false }
//     新值: { name: '张三', loggedIn: true }
//     调用来源: (调用栈)

第七章:Console 方法速查表

scss 复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Console 方法速查表                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  📝 基础输出                                                             │
│  ├─ console.log()      普通日志输出                                     │
│  ├─ console.info()     信息日志(某些浏览器有特殊图标)                  │
│  ├─ console.warn()     警告日志(黄色背景)                              │
│  └─ console.error()    错误日志(红色背景)                              │
│                                                                         │
│  📊 数据展示                                                             │
│  ├─ console.table()    以表格形式展示数组/对象                          │
│  ├─ console.dir()      以对象形式展示(查看属性和方法)                  │
│  └─ console.dirxml()   以 XML/HTML 形式展示 DOM 元素                    │
│                                                                         │
│  📁 分组管理                                                             │
│  ├─ console.group()         创建展开的分组                              │
│  ├─ console.groupCollapsed() 创建折叠的分组                             │
│  └─ console.groupEnd()      结束当前分组                                │
│                                                                         │
│  ⏱️ 性能分析                                                             │
│  ├─ console.time()     开始计时                                         │
│  ├─ console.timeLog()  输出中间时间                                     │
│  ├─ console.timeEnd()  结束计时并输出                                   │
│  └─ console.count()    计数器(统计调用次数)                           │
│                                                                         │
│  🔍 调试追踪                                                             │
│  ├─ console.trace()    打印调用栈                                       │
│  ├─ console.assert()   条件断言(条件为 false 时输出)                  │
│  └─ console.clear()    清空控制台                                       │
│                                                                         │
│  🎨 样式输出                                                             │
│  └─ console.log('%c文字', 'CSS样式')  带样式的输出                      │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

第八章:常见问题与注意事项

8.1 生产环境要移除 console

问题: console 语句会影响性能,也可能泄露敏感信息。

解决方案:

javascript 复制代码
// 方案1:使用环境变量控制
if (process.env.NODE_ENV === 'development') {
  console.log('调试信息')
}

// 方案2:使用构建工具移除
// webpack 配置(使用 terser-webpack-plugin)
optimization: {
  minimizer: [
    new TerserPlugin({
      terserOptions: {
        compress: {
          drop_console: true,  // 移除所有 console
        },
      },
    }),
  ],
}

// 方案3:使用 babel 插件
// babel.config.js
plugins: [
  ['transform-remove-console', { exclude: ['error', 'warn'] }]
]

// 方案4:使用 ESLint 规则
// .eslintrc.js
rules: {
  'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn'
}

8.2 console.log 的异步陷阱

问题: console.log 打印对象时,显示的是引用,不是快照。

javascript 复制代码
const obj = { count: 0 }
console.log(obj) // 可能显示 { count: 1 } 而不是 { count: 0 }
obj.count = 1

解决方案:

javascript 复制代码
// 方案1:使用 JSON.stringify
console.log(JSON.stringify(obj))

// 方案2:使用展开运算符创建浅拷贝
console.log({ ...obj })

// 方案3:使用 JSON.parse + JSON.stringify 创建深拷贝
console.log(JSON.parse(JSON.stringify(obj)))

// 方案4:使用 structuredClone(现代浏览器)
console.log(structuredClone(obj))

8.3 大对象的性能问题

问题: 打印大对象会导致浏览器卡顿。

javascript 复制代码
// ❌ 不好:打印整个大数组
console.log(hugeArray) // 可能有 10000 个元素

// ✅ 好:只打印需要的部分
console.log("数组长度:", hugeArray.length)
console.log("前10个元素:", hugeArray.slice(0, 10))
console.log("第一个元素:", hugeArray[0])

结语:从 console.log 到 console 大师

今天我们学习了 15 个 console 调试技巧:

  1. 用对象包裹变量名 - 自动显示变量名
  2. 用 emoji 标签 - 视觉标记,快速定位
  3. 模板字符串格式化 - 清晰优雅的输出
  4. CSS 样式 - 让日志更醒目
  5. console.table() - 表格展示数据
  6. console.dir() - 查看对象结构
  7. console.dirxml() - 查看 XML/HTML 结构
  8. console.group() - 分组输出
  9. console.groupCollapsed() - 折叠分组
  10. 嵌套分组 - 层级结构
  11. console.time() - 测量执行时间
  12. console.timeLog() - 中间计时
  13. console.count() - 计数器
  14. console.trace() - 调用栈追踪
  15. console.assert() - 条件断言

记住:好的调试习惯能让你的开发效率翻倍。

下次当你想写 console.log('到这了') 的时候,想想有没有更好的方式。


附录:Console 快捷键

yaml 复制代码
浏览器控制台快捷键:

打开控制台:
├─ Windows/Linux: F12 或 Ctrl + Shift + J
└─ Mac: Cmd + Option + J

控制台内操作:
├─ 清空控制台: Ctrl + L (Windows) / Cmd + K (Mac)
├─ 多行输入: Shift + Enter
├─ 执行代码: Enter
├─ 上一条命令: ↑
├─ 下一条命令: ↓
└─ 自动补全: Tab

如果你觉得这篇文章有用,请分享给你那个还在写 console.log('111') 的同事。

也许他需要知道:console 的世界,远比你想象的精彩。 🎨


最后,送给所有程序员一句话:

"调试的艺术,在于问对问题,而不是打更多的 log。" 🔍

愿你的 bug 越来越少,调试越来越快。

相关推荐
摘星编程6 小时前
OpenHarmony + RN:Placeholder文本占位
javascript·react native·react.js
a1117767 小时前
医院挂号预约系统(开源 Fastapi+vue2)
前端·vue.js·python·html5·fastapi
0思必得07 小时前
[Web自动化] Selenium处理iframe和frame
前端·爬虫·python·selenium·自动化·web自动化
行走的陀螺仪9 小时前
uni-app + Vue3编辑页/新增页面给列表页传参
前端·vue.js·uni-app
摘星编程10 小时前
React Native + OpenHarmony:Spinner旋转加载器
javascript·react native·react.js
We་ct10 小时前
LeetCode 205. 同构字符串:解题思路+代码优化全解析
前端·算法·leetcode·typescript
2301_8127314111 小时前
CSS3笔记
前端·笔记·css3
ziblog11 小时前
CSS3白云飘动动画特效
前端·css·css3
越努力越幸运50811 小时前
CSS3学习之网格布局grid
前端·学习·css3
半斤鸡胗11 小时前
css3基础
前端·css