news 2026/3/9 19:44:11

从 proto 到 null:手写 instanceof 揪出对象的“祖宗十八代”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 proto 到 null:手写 instanceof 揪出对象的“祖宗十八代”

手写 instanceof:从原型链里揪出 "血缘关系"🔍 👨‍👩‍👧‍👦

一、回顾原型、原型对象和原型链

在 JavaScript 的世界里,“原型” 这东西就像个神秘的族谱,藏着对象们的家族关系。要搞懂 instanceof,得先扒开这层神秘面纱~

1.什么是原型?

先看三个 “老熟人”:prototype__proto__constructor

prototype是构造函数的 “专属名片”。比如function Animal() {},这个 Animal 构造函数身上就挂着prototype属性,指向一个原型对象,相当于给未来的 “子孙后代” 准备的 "基因库"🧬。

__proto__则是实例对象的 “寻根指针”。当我们用new创建实例时,比如const dog = new Dog(),dog 身上就有个__proto__,偷偷指向构造函数的prototype。就像刚出生的小狗,天生就知道自己的 "基因来源"~

constructor是原型对象上的 “认亲暗号”。每个原型对象都有constructor属性,指向它对应的构造函数。比如Dog.prototype.constructor就指向 Dog,相当于原型对象在说:“我是 Dog 家的基因库!”

2.核心关联规则 —— 原型链

这些小家伙们串起来,就形成了原型链。看下面的代码:

javascript

const arr = []; console.log(arr.__proto__ === Array.prototype); // arr.__proto__指向Array.prototype console.log(arr.__proto__.__proto__ === Object.prototype); // true console.log(arr.__proto__.__proto__.__proto__); // null

数组 arr 的__proto__指向 Array 的原型,Array 原型的__proto__又指向 Object 的原型,Object 原型的__proto__是 null—— 这就是一条完整的原型链,像链条一样🔗一环扣一环,直到尽头。

二、instanceof 介绍

1.instanceof 是什么?

instanceof就像 JavaScript 里的 “亲子鉴定师”,专门判断一个对象是不是某个构造函数的 “后代”(包括直接后代和间接后代)。

看下面的代码:

javascript

Person.prototype = new Animal(); const p = new Person(); console.log(p instanceof Person); // true console.log(p instanceof Animal); // true

p 是 Person 的直接实例,同时也是 Animal 的间接实例(因为 Person 继承了 Animal),所以两次判断都是 true。

2.instanceof 有什么作用?

它的核心作用是检测对象的原型链:判断左边的对象(实例)的原型链上,是否存在右边构造函数的prototype。简单说就是:“你家族谱里有没有这个老祖宗?”

3.基于什么需求创造的 instanceof?

在大型项目里,多人协作时经常会遇到 “这对象到底是谁家的?” 的灵魂拷问。比如你拿到一个dog对象,想知道它能不能调用Animal的方法,这时instanceof就能告诉你:“它是 Animal 家的后代,能调用!” 就像团队协作时,先搞清楚每个人的 “所属部门”,才好分配任务呀~

三、手写 instanceof

明白了原理,咱们也来当回 “亲子鉴定师”,手写一个instanceof

1.手写代码展示

废话不多说,直接上代码:

javascript

function insInstanceOf(left, right) { // 拿实例的__proto__当起点 let proto = left.__proto__; // 顺着原型链一路找 while(proto) { // 找到构造函数的prototype就认亲成功 if(proto === right.prototype) { return true; } // 没找到就继续往上爬 proto = proto.__proto__; } // 爬到顶了还没找到,就是外人 return false; }

验证一下我们手搓的instanceof有没有bug:

javascript

function Animal() {} function Cat() {} Cat.prototype = new Animal(); function Dog() {} Dog.prototype = new Animal(); const dog = new Dog(); console.log(insInstanceOf(dog,Dog)); // true(直接后代) console.log(insInstanceOf(dog,Animal)); // true(间接后代) console.log(insInstanceOf(dog,Object)); // true(所有对象都继承Object) console.log(insInstanceOf(dog,Cat)); // false(猫和狗不是一家)

结果和原生instanceof一模一样!说明咱们的 “亲子鉴定师” 很称职~

2.手写代码的详细解释

  1. 起点设置let proto = left.__proto__—— 从实例的原型指针开始找,就像查族谱从 “本人” 开始翻。
  2. 循环遍历while(proto)—— 只要还没到原型链尽头(proto 不为 null),就继续找。
  3. 核心判断if(proto === right.prototype)—— 如果当前原型就是构造函数的原型,说明是 “自家人”,返回 true。
  4. 继续向上proto = proto.__proto__—— 没找到就往上翻一代,相当于 “查爸爸的爸爸”。
  5. 终点处理:循环结束还没找到,返回 false——“查遍了族谱,确实没这号亲戚”。

这里有个小细节:为什么用let声明proto而不是const?因为proto需要不断更新(往上爬原型链),const声明的变量不能重新赋值呀~

四、面试官会问

  1. instanceof 和 typeof 有啥区别?typeof 是 “粗略分类”,比如typeof []返回 “object”,啥也分不清;而 instanceof 是 “精细认亲”,能准确判断[] instanceof Array为 true。
  2. null 和 undefined 用 instanceof 会怎样?会返回 false!因为它们没有__proto__,原型链都不存在,自然谈不上 "后代"~
  3. 手写 instanceof 时,为什么要比较 prototype 而不是构造函数本身?因为实例的原型链上挂的是构造函数的prototype,而不是构造函数本身。比如dog.__proto__指向Dog.prototype,而不是 Dog 函数~
  4. 原型链的终点是什么?是 null!就像族谱查到最早的老祖宗,再往上就没人啦(arr.__proto__.__proto__.__proto__返回 null)。

五、结语

搞定instanceof的关键,其实是吃透原型链这个 “家族族谱”。从prototype__proto__,从直接实例到间接继承,这些概念环环相扣~
想要搞定这些知识点,可以看看我稀土掘金社区介绍原型、原型对象和原型链的文章:吃透 JS 原型:从构造函数到原型链,一篇讲透核心逻辑JS原型是其面向对象的灵魂,以“委托”而非传统血缘实现继承,以及讲解原型继承的文章:原型继承不翻车:一个空函数如何拯救了父子关系🐱‍💻从 call/apply 的“灵魂传送”到原型链的“共享陷阱”。

下次再遇到 “这对象到底啥来头” 的问题,不妨心里默念:“让我顺着原型链康康~” 实在不行,就把咱们手写的insInstanceOf掏出来,保准能理清所有 "血缘关系"👨‍👩‍👧‍👦

最后友情提示:面试被问手写 instanceof 时,可别光顾着写代码,把原型链的原理讲清楚,才是加分项哦~ 😉

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/7 22:57:44

【Java毕设全套源码+文档】基于springboot的电影院订票信息管理系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/3/8 22:37:27

Unity反向遮罩黑科技:彻底颠覆传统UI设计思维

Unity反向遮罩黑科技:彻底颠覆传统UI设计思维 【免费下载链接】UIMask Reverse Mask of Unity "Mask" component 项目地址: https://gitcode.com/gh_mirrors/ui/UIMask 还在为Unity默认遮罩的局限性而烦恼吗?🤔 想象一下&am…

作者头像 李华
网站建设 2026/3/8 14:57:50

3大技巧玩转Equalizer APO:从入门到精通的音频增强终极指南

还在为音频效果平淡无奇而烦恼吗?想要打造专属的沉浸式音效体验?Equalizer APO作为一款免费开源的音频增强工具,能够帮助你实现专业级的音效定制。今天,就让我带你解锁这款神器的真正潜力! 【免费下载链接】equalizera…

作者头像 李华
网站建设 2026/3/8 18:46:38

10分钟精通AMD处理器调试:SMU工具的完整使用指南

10分钟精通AMD处理器调试:SMU工具的完整使用指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitcode…

作者头像 李华
网站建设 2026/3/8 12:09:01

GridPlayer终极指南:轻松实现多视频同步播放的免费神器

GridPlayer终极指南:轻松实现多视频同步播放的免费神器 【免费下载链接】gridplayer Play videos side-by-side 项目地址: https://gitcode.com/gh_mirrors/gr/gridplayer 在当今多媒体时代,我们经常需要同时观看多个视频内容。无论是教学对比、视…

作者头像 李华
网站建设 2026/3/8 19:40:09

如何用OneMore插件实现终极笔记管理:开源免费的效率神器

如何用OneMore插件实现终极笔记管理:开源免费的效率神器 【免费下载链接】OneMore A OneNote add-in with simple, yet powerful and useful features 项目地址: https://gitcode.com/gh_mirrors/on/OneMore 作为一名OneNote的深度用户,你是否曾经…

作者头像 李华