news 2026/4/16 12:36:20

深入理解 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/4/16 7:45:21

iOS核心开发手册【1.0】

第1章 手势与触摸触摸是iOS交互的核心,它提供了一种非常关键的手段,使用户可以向应用程序表达自己的意图。触摸并不局限于“按下按钮”或“点击键盘”这两种动作。你可以设计并构建出一种应用程序,令其能够以有意义的方式来直接处理用户的手势…

作者头像 李华
网站建设 2026/4/16 7:44:27

医院资源调度优化:床位/医生分配在TensorRT上动态平衡

医院资源调度优化:床位/医生分配在TensorRT上动态平衡 在大型三甲医院的指挥中心,凌晨两点的急诊科刚刚接收了五名车祸伤员。与此同时,心内科ICU有两位患者病情恶化,急需转出普通病房腾出监护床位;而骨科手术室因一台复…

作者头像 李华
网站建设 2026/4/16 7:45:17

Keil入门操作指南:如何烧录程序到单片机

从零开始用 Keil 烧录程序到单片机:新手也能懂的实战指南你有没有遇到过这种情况——代码写得飞快,编译也通过了,可下载到板子上就是不运行?LED 不闪、串口没输出、调试器连不上……别急,这几乎是每个嵌入式初学者都会…

作者头像 李华
网站建设 2026/4/15 15:33:47

Keil4安装完整指南:从下载到运行的全过程详解

Keil4安装实战指南:从零搭建稳定嵌入式开发环境 在嵌入式开发的世界里,一个可靠、高效的IDE往往决定了项目启动的成败。尽管如今Keil Vision6已崭露头角, Keil4(即MDK-ARM v4.x) 依然是许多工程师心中的“定海神针”…

作者头像 李华