什么是原型链(Prototype Chain)?proto和prototype的关系与区别是什么?

一、定义

原型链是 JavaScript 实现继承和属性查找的核心机制,通俗点就是 "对象自己没有某个东西,就一层层向上找别人借" 的链条

  • proto:相当于一个向上查找的链条(工具)
  • prototype(原型对象):存储公共属性/方法

二、__proto__和prototype的区别

对比维度 __proto__(隐式原型) prototype(显式原型)
所属主体 所有对象(除 null)------ 包括实例对象、原型对象本身 仅构造函数(如 ObjectArray、自定义构造函数)
核心作用 建立 "实例→原型对象" 的关联,作为属性查找的 "指针" 存储该构造函数所有实例的共享属性 / 方法(相当于实例的 "模板")
标准性与使用 非 ES 标准(最初是浏览器私有实现),ES6 后纳入但不推荐直接操作;推荐用 Object.getPrototypeOf(obj) 获取原型、Object.setPrototypeOf(obj, proto) 设置原型 ES 标准属性,可直接操作(如给构造函数的 prototype 添加共享方法)

三、实例.proto===其构造函数.prototype

实例通过 proto 找到构造函数的 prototype,从而访问共享内容。

四、用途

4.1 调用对象的「自己没有的属性 / 方法」时(最常用)

TypeScript 复制代码
// 1. 你创建一个数组(数组是"对象"的一种)
const arr = [1,2,3];

// 2. 你调用arr.push(4) --- 但你没给arr写过push方法啊!
arr.push(4);
console.log(arr); // [1,2,3,4](调用成功)

arr自己没有push → 沿原型链找arr.proto → 找到Array.prototype(数组的"上级")→ Array.prototype里有push方法

4.2 多个对象「共用同一个功能」时(省内存)

如果多个对象需要同一个方法(比如 100 个学生都要 "上课"),不用给每个对象都写一遍(浪费内存),把方法放在它们的 "共同上级"(原型对象)里,原型链会帮所有对象找到这个方法。

TypeScript 复制代码
// 1. 定义"学生的共同上级"(原型对象),存一个共用方法"上课"
const 学生原型 = {
  上课: function() {
    console.log(`${this.name}去上课啦!`);
  }
};

// 2. 造2个学生,让它们的"上级"都是「学生原型」(用Object.create连原型链)
const 小明 = Object.create(学生原型);
小明.name = "小明";

const 小红 = Object.create(学生原型);
小红.name = "小红";

// 3. 两个学生都没自己写"上课"方法,但都能调用(原型链找的)
小明.上课(); // 小明去上课啦!
小红.上课(); // 小红去上课啦!

// 关键:两个学生共用同一个"上课"方法,只存了一次,省内存!
console.log(小明.上课 === 小红.上课); // true

4.3 实现【继承】时(子类用父类的功能)

比如你想写一个 "小学生" 类,小学生既要能 "上课"(继承学生的功能),还要能 "写作业"(自己的功能)------ 原型链就是 JS 实现这种 "继承" 的核心。

TypeScript 复制代码
// 1. 定义父类:学生类(基础类)
function Student(name) {
  this.name = name; // 每个学生都有自己的名字
}

// 2. 给学生类的原型添加通用方法(所有学生都会的功能)
Student.prototype.goToClass = function() {
  console.log(`${this.name} 去上常规课啦!`);
};

// 3. 定义子类:小学生类(继承学生类)
function Pupil(name, grade) {
  // 第一步:继承父类的属性(把父类的构造逻辑应用到子类实例上)
  Student.call(this, name); 
  // 第二步:添加子类独有的属性
  this.grade = grade; // 小学生特有:年级
}

// 4. 核心:通过原型链实现方法继承
// 让小学生的原型 指向 学生类的实例(建立原型链关联)
Pupil.prototype = Object.create(Student.prototype);
// 修正构造函数指向(否则Pupil实例的constructor会指向Student)
Pupil.prototype.constructor = Pupil;

// 5. 给小学生类添加独有的方法(子类扩展功能)
Pupil.prototype.doHomework = function() {
  console.log(`${this.name}(${this.grade}年级)开始写小学生作业啦!`);
};

// 6. 测试效果
const xiaoMing = new Pupil("小明", 3);
// 继承父类的方法
xiaoMing.goToClass(); // 输出:小明 去上常规课啦!
// 子类自己的方法
xiaoMing.doHomework(); // 输出:小明(3年级)开始写小学生作业啦!

// 验证原型链关系
console.log(xiaoMing instanceof Pupil); // true(是小学生实例)
console.log(xiaoMing instanceof Student); // true(同时也是学生实例)
相关推荐
Access开发易登软件2 小时前
在 Access 实现标签输入控件:VBA + HTML 混合开发实战
前端·数据库·信息可视化·html·excel·vba·access
studyForMokey2 小时前
【跨端技术ReactNative】JavaScript学习
android·javascript·学习·react native·react.js
૮・ﻌ・2 小时前
Nodejs - 02:模块化、npm、yarn、cnpm
前端·npm·node.js·express·yarn·cnpm·包管理工具
大雷神2 小时前
HarmonyOS APP<玩转React>开源教程十:组件化开发概述
前端·react.js·开源·harmonyos
小小小小宇2 小时前
React useMemo 深度源码解析
前端
tiany5242 小时前
养虾记录-如何配置多agent和多个飞书机器人独立对话
java·前端·飞书
踩着两条虫2 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(十四):扩展与定制之插件系统开发指南
前端·vue.js·ai编程
我命由我123452 小时前
Element Plus - 在 el-select 的每个选项右侧添加按钮
前端·javascript·vue.js·前端框架·ecmascript·html5·js
别看我只是一直狼2 小时前
🚀 程序员高效 Prompt 实战速查手册
前端·后端