前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库JavaScript 原型链属性查找顺序
JSJavaScript对象与原型

在原型链上查找属性时,JavaScript 的解析顺序是怎样的?

读取对象属性时,先检查自身是否带有该属性;若没有,则沿原型链逐级向上查找,找到即停,直到原型为 null 时返回 undefined。

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

原型链属性的解析流程

  1. 自身优先先检查自有属性(own property)是否出现
  2. 链式上溯依次沿 Object.getPrototypeOf 结果向上移动
  3. null停止原型为 null 时未找到则返回 undefined

注意 for...in 会枚举可枚举的继承属性,与 in 运算符一样触发原型链查找,但 Object.keys() 只返回自身可枚举属性。

核心回答

先记住这个答案

当执行 obj.prop 时,JavaScript 先查询 obj 自身的属性描述符。若不存在,则通过 Object.getPrototypeOf(obj) 取得原型并再次查找,如此逐级上溯。该查找遵循就近原则:第一个匹配的属性值会被返回,因此实例上的属性会遮蔽原型上的同名属性。继承的函数在调用时 this 绑定到当前实例,而非原型对象。如果没有属性匹配且原型链尽头是 null,表达式值为 undefined。注意查找是运行时行为,原型变更会立即影响结果。

  • 查找先自身后原型,找到即停。
  • 原型链末端是 null,未找到返回 undefined。
  • 实例属性会遮蔽原型同名属性。

从自身属性到原型链逐级查找的运行时过程

obj.prop 的求值由内部 [[Get]] 实现。规范第一步是取得对象自身的属性描述符,若存在则调用其 value 或 getter 并返回。否则将对象替换为其原型,即 Object.getPrototypeOf(obj) 的结果,重复上述步骤。每个普通对象都有原型,除 Object.create(null) 创建的裸对象外,原型链最终会指向 Object.prototype,而它的原型是 null。

查找不会因一次不匹配而跳过某一层;一旦在某一层发现同名属性,无论它是可枚举、可写还是纯符号,都会立刻返回,后续层不再参与。若遇到属性描述符为 undefined(访问器不存在 getter),返回值也是 undefined。需要了解的是,in 运算符同样沿这条链判断存在性,但 for...in 会枚举链上的可枚举属性。

构造函数实例中的遮蔽与 this 绑定

考虑一个表单构造器 FormField,其原型定义了 validate()。当某个特定实例需要额外的校验逻辑时,直接给该实例赋值一个函数。由于赋值会创建自身属性,后续 instance.validate() 将不再查询原型,这就是遮蔽。遮蔽本身不会修改原型或其他实例,是一种轻量级定制。

若怀疑代码中发生了意外的遮蔽并想定位,可比较 Object.prototype.hasOwnProperty.call(instance,'validate') 与 'validate' in instance 的结果:前者为 true 而后者也为 true,说明存在自身属性;若前者为 false 且后者为 true,则属性来自原型。下方代码演示链式查找与遮蔽。

原型链读取与遮蔽示例JavaScript
const layer1 = { x: 1 };
const layer2 = Object.create(layer1);
const layer3 = Object.create(layer2);
console.log(layer3.x); // 1,沿链找到
layer3.x = 3;
console.log(layer3.x); // 3,自身属性遮蔽
console.log(layer2.x); // 1,不受影响
console.log(layer3.hasOwnProperty('x')); // true
查看输出与解释
1
3
1
true

这段代码先演示了读取时沿链从 layer3 逐级向上找到 layer1 的 x;赋值 layer3.x 创建了自有属性,后续读取优先返回自有值,且层间互不影响。

查找顺序的边界条件与失败形态

有一个容易被忽视的边界:如果位于原型上的属性不可写(writable: false),那么子实例无法创建同名自身属性。在严格模式执行 instance.prop = value 会抛出 TypeError,非严格模式则静默失败;原因是赋值会先检查原型链是否存在不可写的 prop 且没有 setter,并决定是否允许定义新属性。

原型链还可能被 Object.setPrototypeOf 显式地改变,使查找顺序动态化。若构造出循环引用,引擎会拒绝设置成环的 prototype;过长链则可能拉低属性命中性能。要确定属性的真实来源,应结合 Object.getPrototypeOf 遍历或使用 hasOwn 判断每一层,而不是依赖对对象的静态写死理解。

回答前,多想一步

容易答错的地方

误把 for...in 当作只枚举自身属性
for...in 会遍历自身及原型链上的所有可枚举属性,不会停留在自身。若只想处理自有键,必须用 Object.keys 或 hasOwnProperty 过滤。很多面试者在这一细节上头,并因此混淆了枚举与查找的差异。
混淆函数的 prototype 与对象内部原型
构造函数的 prototype 属性仅用于 new 生成实例时设定其实例的内部原型,函数自身原型是 Function.prototype。把这两者混为一条链,就会错误理解继承关系,例如以为 obj.prototype 指向其原型,实际上普通对象没有 prototype 属性。
试着用自己的话回答

面试官还会怎么问?

如何判断一个属性是实例自身还是继承来的?

使用 Object.prototype.hasOwnProperty.call(obj,'prop') 或现代 Object.hasOwn(obj,'prop') 判断自身;'prop' in obj 则包含原型链。二者结合可定位属性在链上的归属。

在继承方法中 this 指向哪里?

this 始终指向最开始时调用该方法的实例对象,而不是方法在原型链上被发现的那一层。这一规则保证实例状态可被共享方法访问,也是 super 调用机制的基础。

原型链查找会影响性能吗?

会,但现代引擎对短链有内联缓存优化。若链过长或频繁动态修改原型,缓存可能失效,导致每次访问都需多层查表。实践中保持链短且结构稳定是减少开销的关键。

从一道题,走向一组知识

把知识连起来

对象与原型

如何区分属性是对象自身属性还是来自原型链?用到哪些 API?

同属「对象与原型」专题,接着看 hasOwnProperty 与 in 区分自身属性和原型属性 在具体场景中的处理方式。

对象与原型

在严格模式下修改 writable:false 的属性会怎样?非严格模式呢?

同属「对象与原型」专题,接着看 writable false 严格模式与非严格模式赋值结果 在具体场景中的处理方式。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Inheritance and the prototype chain

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

本题目录
  1. 先记住这个答案
  2. 从自身属性到原型链逐级查找的运行时过程
  3. 构造函数实例中的遮蔽与 this 绑定
  4. 查找顺序的边界条件与失败形态
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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