一篇文章带你搞懂原型和原型链

我们在理解原型和原型链的时候,喜欢去看概念强行记住,当时以为记住了就懂了可等下次又会忘记,其实是还没有真正弄懂。想要弄懂,就要先知道到底难在哪,理清它们之间的关系,再去看概念性的东西,就轻松很多了。

一、原型和原型链的核心难点拆解

难点 1:__proto__prototypeconstructor 三者的关系(最易混淆)

这三个属性是原型体系的 "三角关系",新手很容易记混、用错,先看核心结论

  • prototype:函数独有,指向"原型对象",原型对象里默认有constructor属性。
  • __proto__所有对象独有,指向自己的"原型对象"。
  • constructor:原型对象独有,指向创建该原型对象的构造函数。

核心公式(必记)

js 复制代码
实例.__proto__ === 构造函数.prototype
构造函数.prototype.constructor === 构造函数
实例.constructor === 构造函数 (本质是通过原型链查找 constructor)
js 复制代码
function Person(name) {
	this.name = name
}
const res = new Person('老王')
// 验证1,实例的隐式原型(__proto__)=== 构造函数的显式原型(prototype)
console.log(res.__proto__ === Person.prototype,) // true
// 验证2,原型对象的constructor指向构造函数
 console.log(Person.prototype.constructor === Person) // true
// 验证3,实例的本身没有constructor 是通过原型链找到原型对象的constructor
 console.log(res.constructor === Person) //true

原型对象本身也是对象,因此它的 __proto__ 会指向更高层的原型对象,最终形成原型链

js 复制代码
// Person.prototype 是对象,其 __proto__ 指向 Object.prototype
Person.prototype.__proto__ === Object.prototype; // true

// Object.prototype 是原型链的顶端,其 __proto__ 为 null
Object.prototype.__proto__ === null; // true

注意点:修改 prototype 会影响 constructor

若直接覆盖构造函数的 prototype(而非添加属性),会丢失原有的 constructor(默认指向 Object),需手动恢复

js 复制代码
// 错误示例:直接覆盖prototype,constructor会指向Object
Person.prototype = {
  sayHi: function() { console.log('Hi'); }
};
p.constructor === Object; // true(不符合预期)

// 正确做法:覆盖后手动设置constructor
Person.prototype = {
  constructor: Person, // 手动指向原构造函数
  sayHi: function() { console.log('Hi'); }
};
p.constructor === Person; // true(恢复预期)

总结三者的核心关系

javascript 复制代码
构造函数(如Person)
  ↓ 拥有
  prototype → 原型对象(如Person.prototype)
                ↓ 拥有
                constructor → 构造函数(Person)
实例(如p)
  ↓ 拥有
  __proto__ → 原型对象(Person.prototype)

二,原型和原型链的核心理解

简单来说每个函数创建都会默认添加一个prototype的属性,创建每个对象也会有一个__proto__的属性,上面也验证过 实例的__proto__(隐式原型)是指向构造函数的prototype(显示原型的)两者是相等的。

构造函数.prototype也是一个对象,所以也会有一个__proto__,指向的是Object.prototype ,因此Object.prototype 也是一个对象,所以也会有__proto__,Object.prototype.proto 指向的却是null,因为这是原型链的最顶层了,顶层就是null

原型链 :实例会先从自身上找,没找到会通过obj.proto 从原型对象上去找(构造函数.prototype),没找到会通过obj.proto .proto 从原型对象上的原型上去找(构造函数.prototype.proto ),直到最顶层Object.prototype去找没找到,就回去Object.prototype.proto 值为null 结束 返回 undefined

js 复制代码
 function Person(name) {
            this.name = name
            this.age = 20
        }

        const obj = new Person('zhangsan')
        Person.prototype.age2 = 30
        Object.prototype.age3 = 40
        console.log(obj.age) //访问的是自身上的属性
        console.log(obj.age2) //访问的是原型对象上的属性
        console.log(obj.age3) //访问的是原型对象的原型上的属性

        /**
         * obj={
         *   console.log(obj.age) 30  先找自身
         * __proto__ === 构造函数.prototype {
         *     console.log(obj.age2) 30  如果自身没有找到 就会去找原型对象
         *   Person.prototype.__proto__ === Object.prototype ={
         *       console.log(obj.age3) 40  原型对象上没有  就会去找原型对象上的原型上去找
         *     }
         *      Object.prototype.__proto__ {
         *        直到最顶层  Object.prototype 它的__proto__ === null  所有原型链的最顶层就是
         *      }  
         *   
         *   }
         * 
         * }
         * **/
相关推荐
我的写法有点潮15 小时前
推荐几个国外比较流行的UI库(上)
前端·javascript·css
鹏多多15 小时前
jsx/tsx使用cssModule和typescript-plugin-css-modules
前端·vue.js·react.js
ssshooter16 小时前
复古话题:Vue2 的空格间距切换到 Vite 后消失了
前端·vue.js·面试
IamZJT_16 小时前
拒绝做 AI 的“饲养员” ❌:前端程序员在 AI 时代的生存与进化指南 🚀
前端·ai编程
MM_MS16 小时前
Halcon控制语句
java·大数据·前端·数据库·人工智能·算法·视觉检测
程序员Agions17 小时前
程序员武学修炼手册(二):进阶篇——小有所成,从能跑就行到知其所以然
前端·程序员
小画家~17 小时前
第四十六: channel 高级使用
java·前端·数据库
小贵子的博客17 小时前
Ant Design Vue <a-table>
前端·javascript·vue.js·anti-design-vue
m0_5027249517 小时前
vue动态设置背景图片后显示异常
前端·css