1.为什么需要继承?
我们先来看一段代码:
function Person(name, age) {
this.name = name
this.age = age
this.money = function () {
console.log('赚钱')
}
}
var zs = new Person()
var ls = new Person()
console.log(zs.name === ls.name) //true
console.log(zs.money === ls.money) //false
通过构造函数的方式创建实例对象,Person是zs和ls实例对象的构造函数,所有的Person对象都有money方法,并且功能相似。当zs和ls两个实例去访问构造函数的方法时,每个实例对象都会在内存中开辟一个单独的空间存放这个方法。他们占用了不同的内存空间,就会导致内存浪费的问题。
所以,我们就需要用到继承。
继承是通过某种方式,让一个对象可以访问到另一个对象里面的属性和方法。
2.JavaScript中的继承方式:
①原型链继承:
子类型的原型为父类型的一个实例对象。实例化父构造函数,将子类的原型指向了父类的实例,子类就可以调用父类原型对象上的私有属性和公有方法。
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.money = function () {
console.log('赚钱')
}
function Student(name, age) {
Person.call(this, name, age)
}
Student.prototype = new Person()
// Student的原型对象指向Person的实例对象就可以访问Person里面的原型对象,Person的原型对象上有money的方法就可以访问
Student.prototype.study = function () {
console.log('学习')
}
var zs = new Student('zs', 18)
console.log(zs)
实例化父构造函数Person,创建了父构造函数的实例对象。父构造函数的实例对象和父构造函数的原型对象在两个不同的内存地址,是两个不同的对象。
通过Student.prototype = new Person(),把实例化对象赋值给子构造函数的原型对象Student.prototype,这就相当于让Student.prototype指向Person的实例对象。Person的实例对象了、可以通过实例对象.__proto__访问到Person的原型对象。在Person的原型对象里有一个”赚钱“的方法,实例对象可以使用这个方法。而Student原型对象指向的是Person的实例对象,所以Student构造函数可以使用”赚钱“这个方法,实现了继承。
当父类新增原型方法或原型属性,子类都可以访问到。想要为子类新增属性和方法,必须写到Student.prototype = new Person()之后执行。
②利用父构造函数继承:
调用父构造函数并修改父构造函数中的this指向子构造函数。
// 利用父构造函数继承属性并且添加属性
function Person(name, age) {
this.name = name
this.age = age
}
function Student(name, age, sex) {
// 继承Person的属性
// 用call方法改变this指向,让Person里的this指向Student
Person.call(this, name, age)
// 添加sex属性
this.sex = sex
}
var student = new Student('zs', 18, '男')
console.log(student)
父构造函数Person里的this指向父构造函数的对象实例,而子构造函数Student的this指向子构造函数的对象实例。
子构造函数通过Person.call(this)调用父构造函数Person并且改变了父构造函数对象实例的this指向了子构造函数的对象实例。此时,子构造函数Student就可以使用父构造函数Person里的属性,实现了继承。
③class继承
ES6中,通过class关键字来定义类,子类可以通过extends继承父类。
// Person类
class Person {
constructor(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
learn() {
console.log('学习')
}
}
var zs = new Person()
console.log(zs)
//es6 student继承Person类 extends
class Student extends Person {
constructor(name, age, gender) {
super(name, age, gender)
}
}
var student = new Student()
console.log(student)