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

isPrototypeOf 和 instanceof 都查原型链,区别在哪?

两者都是沿着对象的原型链往上找,区别在于拿什么去比。proto.isPrototypeOf(obj) 直接拿一个对象去比,obj instanceof Fn 拿的是 Fn.prototype。所以没有构造函数、只用 Object.create 建的对象,只能用 isPrototypeOf 判断。

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

同一条原型链,两种问法

  1. isPrototypeOf调用者本身就是要找的原型对象,适合 Object.create 建的对象
  2. instanceof取右边函数的 prototype 去找,依赖构造函数
  3. Symbol.hasInstance只影响 instanceof,可以让它完全不走原型链

instanceof 每次判断时才去读 Fn.prototype 的当前值。构造函数的 prototype 被换掉后,以前创建的实例就不再是它的 instanceof 了。

核心回答

先记住这个答案

两者都是沿着对象的原型链一层层往上找,区别在于拿什么去比。proto.isPrototypeOf(obj) 直接拿 proto 这个对象去比,问「proto 在不在 obj 的原型链上」;obj instanceof Fn 先取 Fn.prototype,再去链上找。所以 obj instanceof Fn 和 Fn.prototype.isPrototypeOf(obj) 在默认情况下结果相同。不同点有两个:instanceof 右边必须是函数,而且能被 Symbol.hasInstance 改写;isPrototypeOf 对任何对象都能用,也不会被改写。

  • isPrototypeOf 直接查询对象原型链
  • instanceof 通常查询构造器原型
  • instanceof 可使用自定义匹配逻辑
  • isPrototypeOf 不受该钩子改写

同一个对象,两种问法

用构造函数创建的对象,两种写法都能用;用 Object.create 直接指定原型的对象,只有 isPrototypeOf 能判断。

对比两种写法的结果JavaScript
function Foo() {}
const f = new Foo()
console.log(f instanceof Foo, Foo.prototype.isPrototypeOf(f)) // 结果一致

const animal = { eats: true }
const dog = Object.create(animal)
console.log(animal.isPrototypeOf(dog)) // 直接拿对象问
try {
  dog instanceof animal // 右边不是函数
} catch (err) {
  console.log(err.name)
}

Foo.prototype = {} // 换掉原型
console.log(f instanceof Foo, Foo.prototype.isPrototypeOf(f))
查看输出与解释
true true
true
TypeError
false false

animal 只是个普通对象,没有 prototype 属性,也不能被调用,放在 instanceof 右边直接报 TypeError。这就是 isPrototypeOf 存在的意义:原型式继承里只有对象,没有构造函数。 最后一行把 Foo.prototype 换成了新对象,f 的原型链上还是旧的那个,所以两种判断都变成 false。

两者在原型链上怎么查

isPrototypeOf 的过程很简单:从 obj 的原型开始(不包括 obj 自己),逐层用 Object.getPrototypeOf 往上走,每一层和调用者比较是不是同一个对象,找到返回 true,走到 null 返回 false。所以 obj.isPrototypeOf(obj) 是 false,自己不算自己的原型。

instanceof 多了一步。它先看右边有没有 Symbol.hasInstance 方法,普通函数都从 Function.prototype 继承了一个默认实现,默认实现取出 Fn.prototype,再做和上面一样的逐层比较。如果某个类自己写了 static [Symbol.hasInstance],instanceof 的结果就由这个方法决定,可能和原型链完全无关,而 isPrototypeOf 仍然老老实实查链。

两者共同的盲区:跨 iframe
它们比较的都是对象引用。iframe 里的数组,原型是 iframe 自己的 Array.prototype,和主页面的不是同一个对象,所以 arr instanceof Array 和 Array.prototype.isPrototypeOf(arr) 都是 false。判断数组用 Array.isArray,它看的是对象内部标记,不依赖原型对象。
回答前,多想一步

容易答错的地方

以为 isPrototypeOf 只看直接原型
它查的是整条链,不只是上一层。Object.prototype.isPrototypeOf([]) 是 true,因为数组的链是 [] → Array.prototype → Object.prototype。只判断直接原型要用 Object.getPrototypeOf(obj) === proto。
在 Object.create(null) 的对象上调用它
Object.create(null) 建的对象没有原型,身上也就没有 isPrototypeOf 方法,直接写 dict.isPrototypeOf(x) 会报 TypeError。要写成 Object.prototype.isPrototypeOf.call(dict, x)。反过来,用它判断空原型对象不会出错,Object.prototype.isPrototypeOf(dict) 就是 false。
以为两者永远等价
默认情况下 x instanceof F 等于 F.prototype.isPrototypeOf(x),但只要 F 定义了 Symbol.hasInstance,两者就可能不同。还有原始值:1 instanceof Number 是 false,Number.prototype.isPrototypeOf(1) 也是 false,它们都不会把原始值包装成对象再查。
试着用自己的话回答

面试官还会怎么问?

怎么用 isPrototypeOf 手写 instanceof?

先检查右边是不是函数,不是就抛 TypeError;然后返回 Fn.prototype.isPrototypeOf(obj) 即可。要更贴近规范,就在前面先判断 Fn[Symbol.hasInstance] 是否被自定义过。

class B extends A,A.isPrototypeOf(B) 是什么?

是 true。extends 会建立两条链:实例这条是 B.prototype 的原型为 A.prototype;构造函数这条是 B 本身的原型为 A,所以静态方法能被继承。A.isPrototypeOf(B) 查的就是第二条。

TypeScript 里哪个能用来收窄类型?

instanceof 能,TypeScript 会把 if (x instanceof Foo) 里的 x 收窄成 Foo。isPrototypeOf 只返回普通布尔值,编译器不认识它的含义,要收窄得自己写类型守卫函数,返回类型写成 x is Foo。

从一道题,走向一组知识

把知识连起来

对象与原型

Object.keys、getOwnPropertyNames、getOwnPropertySymbols 各能拿到哪些键?

两题都在区分「自身」和「原型链」:Object.keys 这类方法只看自身属性,isPrototypeOf 专门看链上有谁。

对象与原型

一个 class 只能继承一个父类,想复用多组方法怎么办?

用类工厂做 mixin 会插入多层中间类,可以用 isPrototypeOf 和 instanceof 验证链上到底有哪些层。

参考资料

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

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

本题目录
  1. 先记住这个答案
  2. 同一个对象,两种问法
  3. 两者在原型链上怎么查
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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