前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Symbol 原始类型 唯一性
JavaScript值与类型

为什么 Symbol() 每次都不相等,还不能用 new 调用?

Symbol() 每次调用都生成一个全新的唯一值,括号里的描述只是标签,所以两个 Symbol('id') 也不相等。它是原始值,规范特意禁止 new Symbol(),避免造出包装对象。想跨模块共享同一个 Symbol,用 Symbol.for。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#值与类型
先看核心答案读代码示例
理解线索

Symbol 的三个特性

  1. 唯一性每次调用 Symbol() 都生成新值,描述只是给人看的标签
  2. 不能 new用 new 调用直接抛 TypeError,需要包装对象只能写 Object(sym)
  3. 全局注册表Symbol.for(key) 按字符串 key 查找或创建,同一个 key 全局共享

Symbol 不能隐式转成字符串,'key: ' + sym 和模板字符串里直接放 Symbol 都会抛 TypeError。要打印得显式写 String(sym) 或 sym.toString(),或者读 sym.description。

核心回答

先记住这个答案

Symbol 是 ES6 新增的原始类型,typeof 返回 symbol。它最大的特点是唯一:每次调用 Symbol() 都会生成一个和其它任何值都不相等的新值,括号里的描述只是调试时显示的标签,不参与比较,所以 Symbol('id') !== Symbol('id')。它不能用 new 调用,因为规范要求 Symbol 被 new 时直接抛 TypeError,目的是不让人造出 new Number() 那种容易出错的包装对象。需要在不同地方拿到同一个 Symbol 时,用 Symbol.for(key) 从全局注册表里取。

  • typeof 结果是 symbol,是原始值不是对象
  • 每次 Symbol() 都是新值,描述相同也不相等
  • new Symbol() 会抛 TypeError
  • Symbol.for 可从注册表复用值

一段代码看完 Symbol 的特性

唯一性、不能 new、全局注册表、不能隐式转字符串,这四点放在一起跑一遍最直观。

创建、比较和转换JavaScript
const a = Symbol('id')
const b = Symbol('id')
// 描述只是标签,不参与比较
console.log(typeof a, a === b, a.description)
// 不能 new:规范直接禁止
try {
  new Symbol('id')
} catch (err) {
  console.log(err.name)
}
// 全局注册表:同一个 key 拿到同一个 Symbol
console.log(Symbol.for('id') === Symbol.for('id'), Symbol.keyFor(Symbol.for('id')))
// 不能隐式转字符串,但可以显式转
try {
  console.log('key: ' + a)
} catch (err) {
  console.log(err.name)
}
console.log(String(a), a.toString())
查看输出与解释
symbol false id
TypeError
true id
TypeError
Symbol(id) Symbol(id)

Symbol.keyFor 是 Symbol.for 的反向操作,传入注册表里的 Symbol 返回它的 key。对普通 Symbol() 创建的值调用它会返回 undefined,因为那些值从来没进过注册表。 'key: ' + a 抛错是故意的设计。如果 Symbol 能悄悄变成字符串 'Symbol(id)',拿它当属性名拼接时就会退化成普通字符串键,唯一性也就没了。所以规范只允许显式转换。

为什么要禁止 new

new Number(1)、new String('a') 这类写法会得到一个对象,typeof 是 object,放进 if 里永远为真,new Boolean(false) 也是真值,这是老 JavaScript 里公认的坑。Symbol 是 ES6 才加入的类型,设计时就直接堵掉了这条路:用 new 调用 Symbol 抛 TypeError。

包装对象本身还存在,只是不能用 new 得到。写 sym.description 时引擎会临时装箱,调用完就丢掉;真需要一个 Symbol 包装对象可以写 Object(sym),但实际开发里几乎用不到。后来新增的 BigInt 也沿用了同样的规则,new BigInt(1) 同样抛 TypeError。

回答前,多想一步

容易答错的地方

描述相同的 Symbol 是同一个值
描述只是标签。Symbol('id') 调用两次得到两个不同的值。只有 Symbol.for('id') 才会按 key 复用。
Symbol 不能转成字符串
只是不能隐式转换。String(sym)、sym.toString() 都能得到 'Symbol(id)',sym.description 能拿到描述本身。会抛错的是 + 拼接和模板字符串插值。
Symbol.for 创建的值是局部的
正好相反,Symbol.for 的注册表是全局的,甚至不同 iframe 里的代码用同一个 key 都会拿到同一个 Symbol。所以它适合跨模块约定一个公共键,但也就不再「别人猜不到」了。
试着用自己的话回答

面试官还会怎么问?

Symbol 在实际项目里用来做什么?

最常见的是当对象属性键,避免和别人的字符串属性撞名。另一类是内置的 well-known Symbol,比如实现 Symbol.iterator 让对象支持 for...of,实现 Symbol.toPrimitive 控制类型转换。

Symbol 能当 WeakMap 的键吗?

ES2023 起可以用非注册的 Symbol 当 WeakMap 的键,因为它们和对象一样唯一且可以被回收。Symbol.for 创建的 Symbol 不行,它们存在全局注册表里永远不会被回收,传进去会抛 TypeError。

JSON.stringify 遇到 Symbol 会怎样?

对象里值为 Symbol 的属性会被跳过,Symbol 键也会被跳过;数组里的 Symbol 元素会变成 null;直接 JSON.stringify(Symbol()) 返回 undefined。要保留就得自己在 replacer 里处理。

从一道题,走向一组知识

把知识连起来

值与类型

模板字符串和加号拼接,类型转换有什么不一样?嵌套时要注意什么?

模板字符串里直接放 Symbol 会抛错,正好对应 Symbol 不能隐式转字符串这条规则。

值与类型

JSON.stringify 遇到 undefined、函数和 Symbol 会怎么处理?

JSON.stringify 会跳过 Symbol 值和 Symbol 键,序列化对象时要知道这一点。

参考资料

  • JavaScript:值与类型参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 一段代码看完 Symbol 的特性
  3. 为什么要禁止 new
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑