原型和原型链
JavaScript 的原型和原型链主要是为了解决对象之间的属性与方法共享以及继承的问题。 在没有类和传统继承机制的背景下,JS 通过原型让所有对象可以共用同一个函数或属性,而不必为每个实例单独创建副本,从而节省内存并保持逻辑统一。原型链则提供了多级查找机制:当访问一个对象的属性时,如果自身没有,就会沿着
__proto__逐层向上查找,直到找到或抵达 null。这种设计实现了灵活、轻量的对象继承,也是 JS 实现面向对象编程的基础。
📌 为什么需要原型?
想象一下,我们要创建许多个“人”的对象。每个对象都有名字、年龄,并且都能说话。如果没有原型:
🚨 问题: 虽然 p1 和 p2 的 sayHello 功能一样,但它们却是两个不同的函数实例,占用了两份内存空间。如果有成千上万个对象,这种浪费会非常严重。
💡 解决方案 —— 将共用资源放到一个共享地方
我们希望所有“人”对象都共享同一个 sayHello 函数。这个共享的地方,就是原型(Prototype)。
在 JavaScript 中,每当你创建一个函数时,都会同时创建一个对应的原型对象。
关键点:
prototype:是函数才有的属性,它指向一个对象(原型对象),这个对象的用途就是让所有由该函数创建的实例共享方法和属性。__proto__:是每个对象(含函数对象)都有的属性,它指向创建该对象的构造函数的prototype。person1.__proto__ === Person.prototype- ❗注意:
__proto__是一个非标准的历史遗留属性,用于学习和调试。在现代代码中,建议使用Object.getPrototypeOf(obj)获取原型。
🔗 什么是原型链?—— 查找机制
当我们访问一个对象的属性(或方法)时,JavaScript 引擎会:
- 先在对象自身上查找
- 如果没找到,就通过
__proto__去它的原型对象找 - 如果原型对象上也没找到,就再去原型对象的原型对象上找(因为原型对象本身也是一个对象,它也有
__proto__)。 - 一直这样向上查找,直到找到某个原型对象为
null为止(这是查找的终点)。 - 如果直到终点都没找到,则返回
undefined。
这种一层一层向上链接、形成链式关系的结果,就叫做原型链。
代码演示如下:
📊 图示化理解: 下图清晰地展示了实例对象 person1、构造函数 Person 和原型对象之间的完整链条关系:
💬 细心的宝子可能发现了,图中为什么多出了 Function.prototype?
🚀 这是因为在 js 中,函数本身也是对象,所以 Person 是 Function 构造函数的实例。所以 Person 的 __proto__ 指向 Function.prototype
📝 总结
- 原型 (
Prototype)
- 一个简单的对象,用于存储可以被其他对象共享的属性和方法。
- 函数的
prototype属性规定了由它创建的对象能共享什么。 - 对象的
[[Prototype]](可通过__proto__或Object.getPrototypeOf()访问)规定了它自己能使用什么共享资源。
- 原型链 (
Prototype Chain)
- 由多个对象通过
__proto__链接形成的链式结构 - 机制:当访问一个对象的属性时,如果自身没有,就沿着这条链向上查找,直到找到或到达终点(
null)。 - 意义:实现了
JavaScript的“继承”机制。一个对象可以“继承”其原型链上所有对象的属性和方法。
- 补充说明:
constructor属性
每个函数的 prototype 对象都有一个 constructor 属性,指回函数本身。
- Person.prototype.constructor === Person
- person1.constructor === Person(这样实例就能知道自己是由谁创建的了)
🥳🥳🥳 ==你已经看完了,赶快去挑战下吧!
✨赶快测验下吧~✨
- myCar.hasOwnProperty('wheels') 输出什么?
- myCar.proto === Car.prototype 输出什么?
- Car.prototype.proto === ? // 填写完整等式

