第二章:原型与原型链
90%的同学学原型全是背公式、背结论什么「函数有显式原型、对象有隐式原型」背得滚瓜烂熟一做题就废、一面试就懵。核心原因就是你不知道JS为什么要设计原型不懂底层设计初衷所有记忆都是无根之木。今天从设计源头给你讲透。1、原型诞生的底层初衷解决内存浪费问题JS最开始没有原型机制开发者每通过构造函数new一个实例对象都会完整复制一遍构造函数内部的所有方法每个实例的方法都是独立的内存空间。举个直白的例子我定义一个用户构造函数里面有一个sayHi打招呼方法我new 1000个用户实例浏览器就会开辟1000份一模一样的sayHi方法内存。这就造成了极大的内存冗余大量重复代码占用内存页面性能急剧下降。所以JS引擎设计者为了解决实例方法重复占用内存的问题设计出了原型机制所有公共的、通用的方法统一存放在一个公共内存仓库中所有实例共享调用不用重复创建。这个公共仓库就是prototype 显式原型。为了更直观地理解原型机制如何解决内存浪费问题请看下面的对比图2、两大核心指针很多同学混淆两个原型是因为没人告诉你谁专属、谁作用、谁指向谁我给你定死规则1.函数专属prototype 显式原型所有普通函数天生自带prototype属性默认是一个空对象。作用存储当前构造函数所有实例的公共属性、公共方法是公共内存仓库。2.对象专属__proto__ 隐式原型所有对象包括实例对象、原型对象天生自带__proto__属性是一个指针。作用专门用来向上查找自己的公共原型仓库。终身不变铁律底层核心实例对象.__proto__ 构造函数.prototype。实例的查找指针永远指向自己构造函数的公共仓库。3、原型链查找全过程模拟V8引擎真实执行逻辑当你在代码中访问obj.属性/方法时V8引擎不会直接返回undefined会严格按照一套固定链路向上查找这套链路就是原型链1.第一步自身查找引擎优先在当前实例对象自身身上查找该属性/方法如果找到直接返回查找结束。2.第二步原型查找自身没有通过实例的__proto__指针跳转到构造函数的prototype原型对象上查找。3.第三步逐级向上查找如果当前原型上依旧没有继续通过原型对象的__proto__向上跳转层层递进。4.第四步终止查找一直找到顶层Object.prototype这是所有对象的顶层原型。如果顶层依旧没有找到返回undefined。5.终极边界Object.prototype.__proto__ null这是原型链的终点不会继续向上查找。总结所有JS对象的属性读取、方法调用本质都是一次原型链逐级遍历的过程。原型链查找全过程流程图V8引擎真实执行·全中文标注流程图核心注解完全复刻V8引擎真实执行逻辑严格遵循「自身→构造原型→逐级向上→顶层原型→终止判定」的固定链路直观体现原型链逐级遍历、就近查找的核心规则。4、instanceof 底层原理很多同学只会用instanceof判断类型完全不懂底层我用大白话讲透源码逻辑instanceof 本质循环遍历实例的原型链不断向上查找判断构造函数的prototype是否出现在实例的整条原型链上。如果遍历全程能匹配到返回true如果遍历到null依旧没有匹配返回false。关键考点instanceof 判断的是原型链归属不是精准类型所以数组、对象的原型链会存在重叠判定。5、终极总结原型是JS的共享内存优化方案原型链是JS唯一的继承机制所有对象的属性查找、方法调用都是一次完整的原型链遍历。