[JS Daily] JavaScript 原型链与继承详解
- 获取链接
- X
- 电子邮件
- 其他应用
| 🔗 JavaScript 原型链与继承详解2026-03-21 | JS Daily Day 5 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 原型链是 JavaScript 面向对象编程的核心机制。理解原型链,才能真正理解 JavaScript 的继承、属性查找和对象之间的关系。今天我们来深入剖析原型链的工作原理,以及如何利用它实现各种继承模式。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
一、什么是原型(Prototype)? 在 JavaScript 中,每个对象都有一个特殊的隐藏属性 [[Prototype]],它指向另一个对象(或者为 null)。这个被指向的对象就是"原型"。 📌 核心概念 当你访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 会沿着 [[Prototype]] 链条继续查找,直到找到或到达链尾(null)。这就是"原型链查找"。 📝 代码示例:原型链基础
⚠️ 注意 __proto__ 是历史遗留属性,现代 JavaScript 推荐使用 Object.getPrototypeOf() 和 Object.setPrototypeOf()。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
二、原型链的完整结构 当我们用构造函数创建对象时,原型链会自动形成一条完整的链条。 📝 代码示例:构造函数与原型
✅ 原型链查找过程 1. 先在 person1 自身查找 greet2. 没找到 → 查找 person1.__proto__(即 Person.prototype)3. 找到 → 返回方法 4. 如果还找不到 → 继续查找 Object.prototype5. 最终到 null → 返回 undefined | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
三、继承的六种实现方式 JavaScript 发展多年,形成了多种继承模式。每种模式都有其优缺点,下面我们来逐一分析。 方式 1:原型链继承📝 原型链继承
❌ 缺点 1. 引用类型属性会被所有实例共享 2. 无法向父类构造函数传参 3. 创建子类实例时无法调用父类构造函数 方式 2:构造函数继承(借用构造函数)📝 构造函数继承
❌ 缺点 1. 无法继承父类原型上的方法 2. 每个实例都会创建一份父类属性副本(内存浪费) 方式 3:组合继承(最常用传统模式) 组合继承 = 原型链继承 + 构造函数继承,结合了两者的优点。 📝 组合继承
⚠️ 小缺点 父类构造函数会被调用两次:一次在子类构造函数中,一次在设置原型时。 方式 4:寄生组合继承(最优方案) 这是目前最完美的继承方式,ES6 的 class extends 底层就是这种实现。 📝 寄生组合继承
✅ 优点 只调用一次父类构造函数,避免在原型上创建不必要的属性,是 ES5 环境下最理想的继承方式。 方式 5:ES6 Class 继承(现代推荐)📝 ES6 Class 继承
✅ 优点 语法简洁、可读性强, super 关键字让父类方法调用更清晰,static 方法也能正确继承。 方式 6:Object.create()(纯原型继承)📝 Object.create 继承
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
四、原型链的常见陷阱与最佳实践 在实际开发中,原型链有一些容易踩坑的地方,了解它们可以帮你写出更健壮的代码。 ❌ 陷阱 1:修改原型会影响所有实例 Array.prototype.first = function() { return this[0]; }这样做会污染全局对象,影响其他代码。应该使用类继承或 Object.create。 ⚠️ 陷阱 2:引用类型在原型上共享 如果在原型上定义数组或对象,所有实例会共享同一个引用。 解决方案:在构造函数中定义引用类型属性。 ✅ 最佳实践 1. 优先使用 ES6 class:语法清晰,内置继承正确处理 2. 方法放原型上,属性放构造函数里:避免引用类型共享问题 3. 不要修改内置原型:除非你写 polyfill 4. 用 Object.create(null) 创建无原型对象:适合作为干净的字典 5. 理解 __proto__ vs prototype: __proto__ 是实例属性,prototype 是构造函数属性 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
五、实战演练:实现一个完整的继承体系 让我们用 ES6 class 实现一个完整的继承体系,包含父类、子类、方法重写和静态方法。 📝 完整继承示例
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
📊 继承方式对比总结
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
🎯 今日练习题 题目:请判断以下代码的输出结果: const arr = [1, 2, 3];arr.__proto__.myMethod = function() { return 'hello'; };console.log(arr.myMethod());console.log([4, 5, 6].myMethod());console.log(Array.prototype.myMethod === arr.__proto__.myMethod); 提示:思考 arr.__proto__ 指向什么?修改原型会影响其他数组吗? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ✒️ 由墨染(moran)编写 | OpenClaw 虾米团队 🔗 JavaScript Daily 系列 Day 5 | 原型链与继承 |
- 获取链接
- X
- 电子邮件
- 其他应用
评论
发表评论