685 字
3 分钟
JavaScript 原型和原型链

核心定义#

JavaScript 使用原型继承实现对象间共享属性和方法:

  1. 每个对象都有私有属性 __proto__(现代用 Object.getPrototypeOf())指向其原型
  2. 构造函数有 prototype 属性,指向实例的原型对象
  3. 访问对象属性时,若自身不存在,则沿原型链向上查找
  4. 原型链终点是 Object.prototype.__proto__ = null

工作原理#

  1. 创建对象时,自动关联原型对象
  2. 访问属性时:
    • 检查对象自身属性
    • 若无,查找 __proto__ 指向的原型对象
    • 递归直到找到或到达 null
  3. 构造函数 prototype 属性决定实例的原型
flowchart TD 
	A[访问 obj.property] --> B{obj 自身存在?} 
	B -->|是| C[返回属性值] 
	B -->|否| D{有原型?} 
	D -->|是| E[在 obj.__proto__ 查找] 
	D -->|否| F[返回 undefined] 
	E --> B

关键点#

  1. 构造函数new F() 创建对象,其 __proto__ = F.prototype
  2. 原型对象:包含共享方法(如 Array.prototype.push
  3. 原型链obj → Object.prototype → null
  4. 修改原型:动态添加方法(所有实例即时生效)
  5. 性能影响:长原型链查找较慢
  6. 现代替代:ES6 class 是语法糖(底层仍为原型)

常见误区#

  1. 混淆构造函数与实例:误认为实例有 prototype 属性
  2. 原型循环引用A.prototype = B; B.prototype = A 导致无限递归
  3. 覆盖原生原型:修改 Object.prototype 污染所有对象
  4. 性能误判:长原型链属性查找耗时
  5. 继承实现错误:未正确设置 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检查构造函数是否在原型链中出现

关联知识#

  1. new 操作符
  2. ES6 class:语法糖,底层基于原型
  3. 原型方法
    • Object.create(proto):创建指定原型对象
    • Object.getPrototypeOf(obj):获取原型
    • obj.isPrototypeOf():检测对象是否在原型链上
  4. 原型链终点
  5. 属性屏蔽规则
    • 自身属性 > 原型链属性
    • setter 不改变原型属性
  6. 性能优化
    • 避免过深继承层级
    • 高频访问属性直接定义在对象
  7. 设计模式
    • 原型模式(Object.create()克隆对象)
    • 工厂模式

💡 黄金法则

  1. 每个对象都有原型(__proto__
  2. 每个函数都有 prototype 属性(箭头函数除外)
  3. 原型链查找:对象 → 原型 → 原型的原型 → … → null 使用 console.dir() 可视化查看原型链结构!
JavaScript 原型和原型链
https://website-truelovings-projects.vercel.app/posts/frontend/javascript/javascript--原型和原型链/
作者
欢迎来到StarSky的网站!
发布于
2024-12-05
许可协议
CC BY-NC-SA 4.0