news 2026/2/25 19:49:28

深入理解 JavaScript 原型系统:__proto__、prototype 与原型链之间的关系解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 JavaScript 原型系统:__proto__、prototype 与原型链之间的关系解析

标签:JavaScript、原型、原型链、__proto__prototype、前端基础、面试必备

在 JavaScript 中,“一切皆对象”是一句耳熟能详的话。但真正理解这句话背后机制的人却不多。
为什么对象能调用toString()
为什么数组有push()方法?
为什么 objinstanceof Array能判断类型?

答案都指向同一个核心机制:原型(Prototype)与原型链(Prototype Chain)

本文将带你从零开始,彻底搞懂:

  • prototype是什么?
  • __proto__又是什么?
  • 它们之间有何关系?
  • 原型链如何工作?
  • 以及常见的误区与最佳实践。

一、基本概念:prototypevs__proto__

每个 JavaScript 对象(除了null)内部都有一个隐式链接,指向另一个对象 —— 这个被指向的对象就是它的原型

这个隐式链接在规范中叫[[Prototype]],在代码中可通过以下方式访问:

  • 非标准但广泛支持:obj.__proto__
  • 标准方式:Object.getPrototypeOf(obj)

这是最容易混淆的两个属性,但它们的归属和作用完全不同:

属性所属类型作用
prototype函数(Function)对象用于构造函数创建实例时,实例的__proto__会指向它
__proto__所有对象(包括函数)对象指向该对象的原型(即内部[[Prototype]]),用于属性查找

✅ 简单记:

  • 只有函数才有prototype
  • 所有对象都有__proto__

二、一个例子看懂关系

function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, I'm ${this.name}`); }; const alice = new Person('Alice');

此时的关系如下:

  • alice.__proto__ === Person.prototype→ ✅ true
  • Person.prototype.constructor === Person→ ✅ true
  • Person.__proto__ === Function.prototype→ ✅ true(因为Person是函数)

💡new Person()创建的对象,其__proto__自动指向Person.prototype


三、原型链(Prototype Chain)是如何工作的?

当你访问一个对象的属性时,JavaScript 引擎会按以下顺序查找:

  1. 在对象自身查找;
  2. 如果没找到,沿着__proto__向上查找;
  3. 重复此过程,直到Object.prototype
  4. 若仍未找到,返回undefined

示例:

const obj = {}; console.log(obj.toString()); // " [object Object] " // 查找路径: // obj → obj.__proto__ (=== Object.prototype) → 找到 toString

Object.prototype__proto__null,表示原型链终结:

Object.prototype.__proto__ === null; // true

四、ObjectFunction的特殊关系(原型系统的基石)

JavaScript 的整个原型体系建立在两个内置对象之上:ObjectFunction

关键关系:

// 1. Object 和 Function 都是函数 typeof Object; // "function" typeof Function; // "function" // 2. 它们都是 Function 的实例 Object instanceof Function; // true Function instanceof Function; // true // 3. __proto__ 指向 Object.__proto__ === Function.prototype; // true Function.__proto__ === Function.prototype; // true // 4. Function.prototype 是普通对象 Function.prototype.__proto__ === Object.prototype; // true // 5. Object.prototype 是原型链顶端 Object.prototype.__proto__ === null; // true

原型关系图(文字版):

Function ──.__proto__──→ Function.prototype ──.__proto__──→ Object.prototype ──.__proto__──→ null ↑ │ (instanceof) Object ──.__proto__───────────────────────────────────────┘

🔁 这看似“循环”,实则是 JS 引擎初始化时预设的闭环结构。


五、__proto__是标准吗?推荐用法是什么?

虽然obj.__proto__在所有现代浏览器中都支持,但它不是 ECMAScript 标准的一部分(仅在附录 B 作为遗留特性保留)。

✅ 推荐使用标准 API:

操作推荐写法说明
获取原型Object.getPrototypeOf(obj)标准、安全
设置原型Object.setPrototypeOf(obj, proto)谨慎使用(性能差)
创建指定原型的对象Object.create(proto)高效、常用

❌ 不推荐:

obj.__proto__ = SomePrototype; // 非标准,破坏引擎优化

六、常见误区与面试题

1.typeof null为什么是"object"

这是 JavaScript 初期的一个历史性 bug(因底层类型标签用 3 位表示,null的机器码为 000,被误判为对象),但为了兼容性一直保留至今。

2. 为什么[] instanceof Objecttrue

因为数组的原型链:
[] → Array.prototype → Object.prototype
所以[]也是Object的实例。

3. 修改prototype会影响已创建的实例吗?

会!因为实例通过__proto__引用原型对象,不是拷贝。

function Foo() {} const a = new Foo(); Foo.prototype.newMethod = () => 'hi'; console.log(a.newMethod()); // "hi" ✅

七、总结:一张表理清核心概念

概念说明
prototype函数独有的属性,用于 new 创建的对象继承
__proto__所有对象都有,指向其原型(即[[Prototype]]
原型链属性查找机制:沿__proto__向上直到null
Object.prototype原型链的终点之一,提供toStringhasOwnProperty等方法
Function所有函数的构造器,包括ObjectArray
最佳实践Object.create()Object.getPrototypeOf(),避免直接操作__proto__

延伸阅读

  • MDN: 继承与原型链
  • ECMAScript 规范:[[Prototype]][[Call]]内部方法
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/25 11:51:30

打造高性能RAG系统:检索+生成全流程TensorRT加速

打造高性能RAG系统:检索生成全流程TensorRT加速 在企业级智能问答、知识库助手等实时交互场景中,用户对响应速度的要求越来越高。一个看似简单的“提问-回答”过程背后,往往依赖复杂的AI推理链路——尤其是基于检索增强生成(RAG&a…

作者头像 李华
网站建设 2026/2/25 16:18:14

基于ARMCortex-M4F内核的MSP432MCU开发实践【3.1】

2.主模式 通过设置UCMODEx=11、USCYNC=1,置位UCMST控制位,eUSCI_B模块将被配置为I2C主模式。若当前主机是多主机系统的一部分时,必须将UCMM置位,并将其自身地址编程写入UCBxI2COA寄存器。UCA10=0时,选择7位寻址模式; UCA10=1时,选择10位寻址模式。UCGCEN控制位选择eUSC…

作者头像 李华
网站建设 2026/2/24 11:19:47

STM32串口DMA与空闲中断联合应用实战案例

STM32串口DMA与空闲中断联合应用实战:如何实现高效、低CPU占用的不定长数据接收?在嵌入式开发中,你是否遇到过这样的场景?多个传感器通过串口持续发送数据,主控MCU却因频繁中断而“卡顿”;接收到的数据总是…

作者头像 李华
网站建设 2026/2/24 2:36:19

药品说明书简化:专业术语解释在TensorRT上自动转换

药品说明书简化:专业术语解释在TensorRT上自动转换 在医院候诊室里,一位老年患者拿着刚开的处方药说明书皱眉——“本品通过抑制血管紧张素转化酶活性,降低外周血管阻力”这样的句子对他而言如同天书。而与此同时,医生正被堆积如山…

作者头像 李华
网站建设 2026/2/20 9:44:44

arduino小车与传感器融合教学:项目应用解析

从遥控玩具到智能小车:用传感器融合点亮你的Arduino机器人你有没有过这样的经历?花了一周时间把Arduino小车组装好,连上电机、装上轮子、下载了示例代码,按下按钮——结果它一头撞墙,转个弯又卡在角落里出不来。明明是…

作者头像 李华