继承
JavaScript 支持继承,这是指在一个对象(称为“子类”)中继承另一个对象的属性和方法(称为“父类”)
在 JavaScript 中,继承可以通过构造函数、原型链、实例、拷贝实现。
构造继承
构造继承是指创建一个新的对象,并将其父对象的属性和方法复制到新对象上,并对新对象进行初始化。
// 定义父对象
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`)
}
// 定义子对象
function Student(name, age, major) {
Person.call(this, name, age)
this.major = major
}
// 继承父对象的方法
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
// 定义子对象自己的方法
Student.prototype.study = function () {
console.log(`I am studying ${this.major}.`)
}
const john = new Student('John Doe', 22, 'Computer Science')
john.sayHello()
john.study()在这个示例中,通过将父对象的方法复制到子对象的原型链上,实现了构造继承。
原型继承
原型继承通过将子对象的原型指向父对象来实现继承。以下是一个简单的原型继承的例子:
function Parent(name) {
this.name = name
}
Parent.prototype.sayName = function () {
console.log('My name is ' + this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
Child.prototype.sayAge = function () {
console.log('My age is ' + this.age)
}
var child = new Child('John', 25)
child.sayName() // My name is John
child.sayAge() // My age is 25先定义了一个 Parent 函数,它有一个 name 属性和一个 sayName 方法。然后,我们定义了一个 Child 函数,该函数继承了 Parent 函数。我们在 Child 函数中通过调用 Parent.call(this, name) 来初始化 name 属性,并且在 Child.prototype 上添加了一个 sayAge 方法。最后,我们创建了一个 Child 的实例,可以使用继承过来的 sayName 方法和 sayAge 方法。
从 ECMAScript 6 开始,JavaScript 增加了 class 关键字,可以更方便地实现继承。
class Parent {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name)
}
}
class Child extends Parent {
constructor(name, age) {
super(name)
this.age = age
}
}
var child = new Child('Tom', 20)
console.log(child.name) // Tom
console.log(child.age) // 20
child.sayName() // Tom实例继承
原型链的实现原理是,每个对象都有一个指向它的构造函数的原型的指针,以及一个指向该对象的原型的指针,而原型对象又有自己的原型对象。通过这种方式,所有的对象都构成了一个原型链,我们可以通过在原型对象上定义属性和方法来让它们被所有对象继承。
例如,我们可以定义一个基础对象 Animal,并在其原型对象上定义一个 sayHello 方法:
function Animal() {}
Animal.prototype.sayHello = function () {
console.log('Hello, I am an animal.')
}然后,我们可以定义一个继承 Animal 的对象 Dog:
function Dog() {}
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog现在,我们可以创建一个 Dog 对象并调用 sayHello 方法:
const dog = new Dog()
dog.sayHello() // 输出 "Hello, I am an animal."由此可见,Dog 对象继承了 Animal 的 sayHello 方法。
拷⻉继承
拷贝继承是指通过复制一个对象的属性和方法到另一个对象中来实现继承。这种方法主要通过使用一个循环或工具函数,将父对象的属性复制到子对象中。但是,拷贝继承存在一些问题,例如无法在父对象中更改子对象的属性。因此,拷贝继承通常不是首选的继承方法。
以下是一个 JavaScript 拷贝继承的示例:
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
}
// 将父对象的属性和方法复制到子对象上
for (var prop in Parent.prototype) {
Child.prototype[prop] = Parent.prototype[prop]
}
var child = new Child('John', 30)
child.sayName() // 输出 'John'
console.log(child.age) // 输出 30在上面的示例中,我们通过循环将父对象的属性和方法复制到了子对象的原型上,从而实现了拷贝继承。
原型 prototype 机制或 apply 和 call ⽅法去实现较简单,建议使⽤构造函数与原型混合⽅式
function Parent() {
this.name = 'wang'
}
function Child() {
this.age = 28
}
Child.prototype = new Parent() //继承了Parent,通过原型
var demo = new Child()
alert(demo.age)
alert(demo.name) //得到被继承的属性