前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库String valueOf toString 区别
JavaScript值与类型

String 的 valueOf 和 toString 有区别吗?为什么对 new String 调用会拿到原始字符串?

对字符串来说,valueOf 和 toString 做的是同一件事:取出 String 包装对象内部保存的原始字符串。所以 new String('hi').valueOf() 得到的是 typeof 为 string 的原始值。两者的差别不在返回值,而在类型转换时谁先被调用。

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

包装对象里的原始值

  1. 包装对象new String('hi') 生成一个对象,内部存着原始字符串 'hi'
  2. valueOf 和 toString都直接返回这个内部原始字符串,规范里两者的步骤一样
  3. 转换时的调用顺序转字符串时先 toString,默认转换(如 +)时先 valueOf

String.prototype.toString 覆盖了 Object.prototype.toString,所以字符串对象调用 toString 得到的是内容本身,而不是 '[object String]'。想看类型标签得写 Object.prototype.toString.call(s)。

核心回答

先记住这个答案

String.prototype.valueOf 和 String.prototype.toString 在规范里的实现一模一样:检查 this 是原始字符串还是 String 包装对象,然后返回里面的原始字符串。所以对 new String('hi') 调用任意一个,拿到的都是原始值 'hi',而不是对象。两者真正的区别体现在隐式类型转换上:转成字符串的场景(模板字符串、String())先调 toString,默认转换的场景(+ 拼接、== 比较)先调 valueOf。

  • 两个方法都返回内部的原始字符串,结果相同
  • 包装字符串经 valueOf 得到原始值
  • 模板字符串与 + 的转换提示不同
  • this 不是字符串时两者都抛 TypeError

包装对象和原始值的区别

'hi' 是原始值,new String('hi') 是一个对象,对象内部存着那个原始字符串。可以把包装对象想象成一个盒子,valueOf 和 toString 都是把盒子里的东西拿出来。

对照调用结果和转换顺序JavaScript
const prim = 'hi'
const wrapped = new String('hi')
// 两个方法返回的都是原始字符串
console.log(typeof wrapped, typeof wrapped.valueOf(), typeof wrapped.toString())
console.log(wrapped === 'hi', wrapped.valueOf() === 'hi')
// 原始值调用方法时,引擎临时包一层,调用完就丢掉
console.log(prim.valueOf() === prim.toString())
// 两者都要求 this 是字符串或 String 对象
try {
  String.prototype.valueOf.call({})
} catch (err) {
  console.log(err.name)
}
// 只改 toString,看两种转换各调了谁
wrapped.toString = () => 'custom'
console.log(`${wrapped}`, wrapped + '')
查看输出与解释
object string string
false true
true
TypeError
custom hi

wrapped === 'hi' 是 false,因为严格相等不做类型转换,一个是对象一个是字符串。取出原始值后再比较就是 true。 最后一行最关键。给 wrapped 单独覆盖了 toString,模板字符串走「转字符串」流程,先调 toString,输出 custom;+ 走默认转换流程,先调 valueOf,拿到的还是原来的 hi。

平时为什么感觉不到包装对象

写 'hi'.toUpperCase() 时,原始值本身没有方法,引擎会临时创建一个 String 包装对象,调用完方法就丢弃,这个过程叫自动装箱。所以原始字符串也能调用 valueOf 和 toString,结果就是它自己。

真正需要 valueOf 的场景很少,基本只有拿到了一个 new String() 创建的对象,想把它还原成原始值时。更常见的写法是直接 String(x),它对包装对象和原始值都能返回原始字符串。

回答前,多想一步

容易答错的地方

toString 返回字符串,valueOf 返回对象本身
这是把 Object.prototype.valueOf 的行为套到了字符串上。普通对象的 valueOf 确实返回对象自身,但 String.prototype.valueOf 被重写过,返回的是原始字符串。
new String('a') == new String('a') 是 true
是 false。两边都是对象,== 比较的是引用,不会触发 valueOf。只有一边是原始值时,== 才会把对象转成原始值再比。
用 new String() 创建字符串更规范
没有任何好处。包装对象 typeof 是 object,在条件判断里永远为真,new String('') 也是真值,很容易引出 bug。直接写字面量就行。
试着用自己的话回答

面试官还会怎么问?

Number 和 Boolean 的 valueOf 也是这样吗?

是。Number.prototype.valueOf 返回内部的原始数字,Boolean.prototype.valueOf 返回内部的原始布尔值,思路完全一样。区别只是 toString 的输出格式:数字的 toString 还能传进制参数。

自定义对象想控制转字符串的结果,该重写哪个?

只关心字符串结果就重写 toString,模板字符串和 String() 会用到它。想同时控制 + 和数学运算,就实现 Symbol.toPrimitive,它接收 hint 参数,一个方法就能覆盖所有转换场景,优先级也最高。

怎么判断一个值是字符串对象还是原始字符串?

typeof 能区分:原始字符串是 string,包装对象是 object。如果两种都想识别为字符串,用 Object.prototype.toString.call(x) === '[object String]',两者都会返回这个标签。

从一道题,走向一组知识

把知识连起来

值与类型

用 Symbol 当对象的键,和字符串键有什么不同?哪些 API 会忽略它?

valueOf() 取出的字符串原始值能当对象属性键;Symbol 也是可用的原始值键,且不会与同名字符串冲突。

值与类型

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

Symbol 也有包装对象,但不能用 new Symbol() 创建,和 new String() 正好形成对比。

参考资料

  • JavaScript:值与类型参考资料

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

本题目录
  1. 先记住这个答案
  2. 包装对象和原始值的区别
  3. 平时为什么感觉不到包装对象
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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