一、继承的核心:原型链机制
JavaScript使用原型链实现继承,理解继承机制需要先掌握三个核心概念:
-
1.每个构造函数(constructor)都有prototype属性指向原型对象
-
2.每个实例都有__proto__属性指向构造函数的原型对象
-
3.原型对象中的constructor属性指回构造函数
function Animal(name) {
this.name = name
}
// 原型方法
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise`)
}
let dog = new Animal('Buddy')
dog.speak() // "Buddy makes a noise"
原型链继承示例:
function Dog(name) {
Animal.call(this, name) // 二次调用父类构造函数的伏笔
}
Dog.prototype = new Animal() // 第一次调用父类构造函数
Dog.prototype.constructor = Dog
let husky = new Dog('Husky')
husky.speak() // 继承父类方法
二、继承方式演进与优化
1. 构造函数继承(解决属性共享问题)
function Parent(name) {
this.name = name
this.colors = ['red', 'blue']
}
function Child(name) {
Parent.call(this, name) // 核心代码
}
let c1 = new Child('Jack')
c1.colors.push('green')
let c2 = new Child('Lily')
console.log(c2.colors) // ['red', 'blue'] 独立属性
2. 组合继承优化版(ES5最佳实践)
function inheritPrototype(child, parent) {
let prototype = Object.create(parent.prototype)
prototype.constructor = child
child.prototype = prototype
}
function Parent(name) {
this.name = name
}
Parent.prototype.sayName = function() {
console.log(this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
inheritPrototype(Child, Parent)
// 添加子类方法
Child.prototype.sayAge = function() {
console.log(this.age)
}
3. ES6 Class继承
class Animal {
constructor(name) {
this.name = name
}
speak() {
console.log(`${this.name} makes a noise`)
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name) // 必须在使用this之前调用
this.breed = breed
}
bark() {
console.log(`${this.name} barks!`)
}
}
let husky = new Dog('Max', 'Husky')
husky.bark() // "Max barks!"
三、进阶技巧
1. Mixin模式实现多重继承
let sayMixin = {
say(phrase) {
console.log(`${this.name} says: ${phrase}`)
}
};
class User {
constructor(name) {
this.name = name
}
}
Object.assign(User.prototype, sayMixin)
new User('John').say('Hello') // John says: Hello
2. 静态属性继承
class Parent {
static TYPE = 'PARENT'
}
class Child extends Parent {
static getType() {
return `${super.TYPE}_CHILD`
}
}
console.log(Child.getType()) // "PARENT_CHILD"
四、总结
-
1.现代项目优先使用Class语法,保持代码简洁性
-
2.需要支持老旧浏览器时使用寄生组合式继承
-
3.慎用多重继承,优先考虑组合模式
-
4.使用instanceof进行类型检查时注意原型链影响
-
5.避免修改内置对象的原型链
理解JavaScript继承机制的关键在于掌握原型链的工作原理,Class语法虽然简洁,但其本质仍然是基于原型的继承实现。