前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库Object.create(null) 无原型对象特点
JavaScript对象与原型

Object.create(null) 创建的对象有什么特别?哪些方法用不了?

Object.create(null) 创建的对象原型是 null,Object.prototype 上的方法一个都继承不到。所以 toString、hasOwnProperty 都没有,模板字符串拼接会报 TypeError。好处是它是一个干净的字典,键名不会和继承属性撞车。

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

一个没有原型的纯字典

  1. [[Prototype]] 为 null属性查找只看自身,找不到直接返回 undefined
  2. 实例方法缺失toString、valueOf、hasOwnProperty 都读不到,调用就报错
  3. 静态方法照常可用Object.keys、Object.hasOwn、JSON.stringify 都不依赖原型

它不是不能参与 instanceof,放在左边完全合法,只是 obj instanceof Object 返回 false。很多人把这点说反了。

核心回答

先记住这个答案

Object.create(null) 返回的对象没有原型,它的 [[Prototype]] 是 null。平时对象身上的 toString、valueOf、hasOwnProperty、isPrototypeOf 都来自 Object.prototype,这个对象一个都继承不到。直接调用这些方法会报 TypeError,放进模板字符串或 String() 里也会报错,因为转字符串时找不到 toString 和 valueOf。它的用处是当纯字典,键名随便起,不会和原型上的属性冲突。

  • 空原型对象没有继承方法
  • 空原型对象直接转字符串会报错
  • 判断自有键用 Object.hasOwn,别调实例方法
  • 适合当字典,in 不会误命中 toString

实际跑一下看哪些会失败

平时写 {},等价于 Object.create(Object.prototype)。把原型换成 null,差别马上就出来了。

无原型对象的几个表现JavaScript
const dict = Object.create(null)
dict.name = 'Tom'

console.log(Object.getPrototypeOf(dict)) // null
console.log(typeof dict.toString) // undefined,没继承到
console.log('toString' in dict) // false,普通对象这里是 true
console.log(Object.hasOwn(dict, 'name')) // true,静态方法照常用
console.log(dict instanceof Object) // false,但不报错
try {
  dict.hasOwnProperty('name')
} catch (e) {
  console.log(e.name) // 方法不存在
}
try {
  console.log(`${dict}`)
} catch (e) {
  console.log(e.name) // 转不成字符串
}
查看输出与解释
null
undefined
false
true
false
TypeError
TypeError

规律很好记:凡是「对象自己身上调用」的方法都失效,凡是 Object.xxx(obj) 这种静态方法都正常。Object.keys、Object.entries、JSON.stringify 都能用,因为它们不需要从对象的原型上找东西。 ${dict} 报错的原因是,转原始值时引擎会依次找 Symbol.toPrimitive、valueOf、toString,三个都没有,只能抛 TypeError。在控制台里打印没问题,但写日志时拼字符串就会炸。

为什么要专门造一个没原型的对象

拿普通对象当字典,有个隐藏的坑。比如统计单词出现次数,用 counts[word] 存。碰到单词 constructor 时,counts['constructor'] 一开始就不是 undefined,而是 Object 函数,计数逻辑就乱了。用 in 判断键是否存在也一样,'toString' in {} 是 true。

Object.create(null) 把这个问题从根上去掉了:没有原型,就没有任何「天生就有」的键。所以不少库内部的缓存表都这样创建。

它还能挡一部分原型污染。如果有人往 Object.prototype 上加了属性,普通对象都能读到,无原型对象读不到。另外,在它身上写 dict.__proto__ = x 不会改原型,这里的 __proto__ 只是一个普通键。因为 __proto__ 的 getter 和 setter 定义在 Object.prototype 上,这个对象继承不到,写进去就是个叫 __proto__ 的普通属性。

和 Map 怎么选
新代码当字典,Map 通常更合适:键可以是任意类型,有 size,按插入顺序遍历,也没有原型冲突。无原型对象的优势是能直接 JSON.stringify,读写语法就是普通的点和方括号,适合要序列化或者要和现有对象接口保持一致的场景。
回答前,多想一步

容易答错的地方

说它不能用于 instanceof
dict instanceof Object 完全合法,只是返回 false,因为原型链上找不到 Object.prototype。真正会报错的是把它放在 instanceof 右边,因为右边要求是函数或者带 Symbol.hasInstance 的对象,这和「无原型」没关系,任何普通对象放右边都报错。
以为 Object.create(null) 和 {} 只是少几个方法
少的不只是方法,还有隐式转换能力。dict + ''、String(dict)、alert(dict) 都会抛错。一些第三方库拿到对象就调 obj.hasOwnProperty,传进去也会直接报错,所以对外暴露的数据最好别用它。
判断自有属性还写 dict.hasOwnProperty(key)
它没有这个方法。要么用 Object.hasOwn(dict, key),要么借用 Object.prototype.hasOwnProperty.call(dict, key)。其实对无原型对象来说,key in dict 也等价于判断自有属性,因为原型链只有它自己一层。
试着用自己的话回答

面试官还会怎么问?

能不能把一个普通对象改成无原型的?

可以用 Object.setPrototypeOf(obj, null)。但修改已有对象的原型会让引擎放弃针对它的优化,性能不好,更推荐一开始就用 Object.create(null) 创建。

Object.create 的第二个参数是干什么的?

它接收一个属性描述符对象,和 Object.defineProperties 的格式一样,比如 Object.create(null, { id: { value: 1, enumerable: true } })。没写的描述符字段默认都是 false,所以这样定义的属性默认不可写、不可枚举、不可删除。

怎么让无原型对象在控制台或日志里正常显示?

最简单是 JSON.stringify(dict),或者先展开成普通对象 { ...dict } 再处理。展开运算符只复制自有可枚举属性,得到的新对象原型是 Object.prototype,所有方法又都回来了。

从一道题,走向一组知识

把知识连起来

对象与原型

属性设成 configurable:false 之后,哪些操作就做不了了?

Object.create 的第二个参数就是属性描述符,configurable 这些字段在那篇讲。

对象与原型

可选链 ?. 和用 && 一层层判断,有什么不一样?

无原型对象上调方法前常用 obj.toString?.() 兜底,可选链的短路规则在那篇展开。

参考资料

  • JavaScript:对象与原型参考资料

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

本题目录
  1. 先记住这个答案
  2. 实际跑一下看哪些会失败
  3. 为什么要专门造一个没原型的对象
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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