685 字
3 分钟
JavaScript 原型和原型链
.png)
核心定义
JavaScript 使用原型继承实现对象间共享属性和方法:
- 每个对象都有私有属性
__proto__
(现代用Object.getPrototypeOf()
)指向其原型 - 构造函数有
prototype
属性,指向实例的原型对象 - 访问对象属性时,若自身不存在,则沿原型链向上查找
- 原型链终点是
Object.prototype.__proto__ = null
工作原理
- 创建对象时,自动关联原型对象
- 访问属性时:
- 检查对象自身属性
- 若无,查找
__proto__
指向的原型对象 - 递归直到找到或到达
null
- 构造函数
prototype
属性决定实例的原型
flowchart TD A[访问 obj.property] --> B{obj 自身存在?} B -->|是| C[返回属性值] B -->|否| D{有原型?} D -->|是| E[在 obj.__proto__ 查找] D -->|否| F[返回 undefined] E --> B
关键点
- 构造函数:
new F()
创建对象,其__proto__ = F.prototype
- 原型对象:包含共享方法(如
Array.prototype.push
) - 原型链:
obj → Object.prototype → null
- 修改原型:动态添加方法(所有实例即时生效)
- 性能影响:长原型链查找较慢
- 现代替代:ES6
class
是语法糖(底层仍为原型)
常见误区
- 混淆构造函数与实例:误认为实例有
prototype
属性 - 原型循环引用:
A.prototype = B; B.prototype = A
导致无限递归 - 覆盖原生原型:修改
Object.prototype
污染所有对象 - 性能误判:长原型链属性查找耗时
- 继承实现错误:未正确设置
Child.prototype = new Parent()
应用场景
场景 | 示例 | 原型机制作用 |
---|---|---|
方法共享 | Array.prototype.map = function(){} | 所有数组实例共享方法 |
原型继承 | Dog.prototype = Object.create(Animal.prototype) | 实现类式继承 |
属性访问优化 | 高频访问属性直接定义在对象自身 | 避免原型链查找开销 |
动态扩展对象能力 | String.prototype.trim = function(){} | 为原生类型添加新方法 |
对象创建 | const obj = Object.create(proto) | 显式指定原型创建对象 |
类型检测 | obj instanceof Constructor | 检查构造函数是否在原型链中出现 |
关联知识
- new 操作符
- ES6 class:语法糖,底层基于原型
- 原型方法:
Object.create(proto)
:创建指定原型对象Object.getPrototypeOf(obj)
:获取原型obj.isPrototypeOf()
:检测对象是否在原型链上
- 原型链终点:
- 属性屏蔽规则:
- 自身属性 > 原型链属性
- setter 不改变原型属性
- 性能优化:
- 避免过深继承层级
- 高频访问属性直接定义在对象
- 设计模式:
- 原型模式(
Object.create()
克隆对象) - 工厂模式
- 原型模式(
💡 黄金法则:
- 每个对象都有原型(
__proto__
) - 每个函数都有
prototype
属性(箭头函数除外) - 原型链查找:对象 → 原型 → 原型的原型 → … → null 使用
console.dir()
可视化查看原型链结构!