红宝书第十讲:用宠物店案例+图示拆解JavaScript构造函数与原型链
一、为什么说构造函数是对象的”生产模具”?
想象你经营着一家宠物店🐾,每天需要创建大量小狗对象。每个小狗都有品种、年龄、技能等属性。如果手工创建100只金毛犬,代码会变成这样:
const dog1 = { breed: '金毛', age: 2, skill: '捡飞盘' }; const dog2 = { breed: '金毛', age: 3, skill: '游泳' }; // ...重复98次
1.1 构造函数的批量生产优势
通过构造函数,我们可以像使用模具般批量生产:
function Dog(breed, age, skill) { this.breed = breed; this.age = age; this.skill = skill; } const golden1 = new Dog('金毛', 2, '捡飞盘'); const golden2 = new Dog('金毛', 3, '游泳');
▲ 图示说明new关键字的四个步骤:创建空对象→绑定this→添加属性→返回对象
二、原型链的”套娃”继承机制揭秘
2.1 原型的三位一体关系
- 构造函数.prototype → 存储公共方法的原型对象
- 实例.__proto__ → 指向构造函数的原型
- 原型.constructor → 指回构造函数本身
▲ 原型链查找过程示意:实例对象→Dog原型→Animal原型→Object原型→null
2.2 实现多级继承的”套娃”技巧
function Animal(type) { this.type = type || '哺乳动物'; } function Dog(breed) { this.breed = breed; } // 关键继承步骤 Dog.prototype = new Animal(); const myDog = new Dog('金毛'); console.log(myDog.type); // 输出"哺乳动物"
注意点:
- 要在继承后重置constructor指向:
Dog.prototype.constructor = Dog
- 避免在原型中直接定义引用类型值,否则所有实例会共享该值
三、从原理到实践:继承方案的演进
继承方式 | 优势 | 缺陷 |
---|---|---|
原型链继承 | 简单直观 | 共享引用类型属性 |
构造函数继承 | 解决属性隔离 | 无法复用方法 |
组合继承 | 属性方法分离 | 两次调用构造函数 |
3.1 现代开发的最佳实践
推荐使用ES6的class语法糖:
class Animal { constructor(type) { this.type = type; } } class Dog extends Animal { constructor(type, breed) { super(type); this.breed = breed; } }
四、常见问题解答
4.1 为什么修改原型要放在继承之后?
如果先给Dog原型添加方法再继承,这些方法会被Animal实例覆盖。正确的顺序应该是:
- 建立原型继承关系
- 添加原型方法
- 重置constructor指向
4.2 instanceof的判断原理
该运算符通过检查原型链来判断对象类型:
myDog instanceof Dog; // true myDog instanceof Animal; // true myDog instanceof Object; // true
通过本文的宠物店案例和图示解析,相信你已经掌握了构造函数与原型链的核心原理。在实际开发中,建议结合调试工具查看对象的[[Prototype]]链,这将帮助您更直观地理解JavaScript的继承机制。