ES6 之前官方并没有提供一种实现继承的语法,所以大部分继承方式都是程序员通过代码在模拟.常见的继承方式有以下几种:
1、原型继承
原型继承可以继承构造函数中的属性,也可以继承原型链上的方法
function Person(name, age) {
this.type = 'human'
this.name = name
this.age = age
}
Person.prototype.sayName = function () {
console.log('hello ' + this.name)
}
function Student(name, age) {
Person.call(this, name, age)
}
Student.prototype = new Person()
Student.prototype.constructor = Student;
var s1 = new Student('张三', 18)
console.log(s1);
console.log(s1.type) // => human
s1.sayName() // => hello 张三
另外说:call方法可以改变函数的this指向,第二个参数是参数列表。
即在上面代码中,将Person的this指向修改为指向Student,此时可以继承来自Person父类的属性
Student.prototype = new Person() ---- 将Student的原型对象设置为Person的构造函数实例化对象,那么此时Student的实例化对象可以访问原型链上的方法。
但是此时student的constructor属性改变,指向person,所以需要将constructor重新指向Student
即Student.prototype.constructor = Student
2、构造函数继承
构造函数继承只能继承属性,无法继承构造函数原型链上的方法;
function Person(name, age, gender) {
this.name = name ;
this.age = age ;
this.gender = gender ;
}
Person.prototype.sayHi = function () {
console.log("I'm " + this.name);
}
function Student(name, age, gender, score) {
this.score=60
Person.call(this, name, age, gender) //调用Person的同时 指向Student这个函数
}
var s1 = new Student('张三', 18,'男')
console.log(s1.name, s1.age) // => 张三 18
console.log(s1);
通过Person.call(this, name, age, gender) ,修改this指向,此时调用Person函数,但是this指向Student,也就是说,此时可以在Student中访问Person的属性
3、组合继承
function SuperType(name, age) {
this.name = name;
this.age = age;
this.f = [1, 2, 3, 4]
}
SuperType.prototype.sayName = function () {
console.log(this.name)
}
function SubType(name, age) {
SuperType.call(this, name, age) //继承SuperType,并传递参数
this.job = 'actor'
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayHello = function () {
console.log('hello')
}
var h = new SubType('hua', 18);
h.sayName()//hua
h.f.push(5)
console.log(h.f) //1,2,3,4,5
var n = new SubType('li',20);
console.log(n.f) //1,2,3,4 原来的取值并没有发生改变
每一次构造出来的实例所得到的属性都不受前一个的影响,即使前一个修改了实例中的属性,但是其他实例所继承的仍然是父级所原本拥有的
ES6后使用extends关键字实现继承
class Person{
constructor(name){
this.name = name
}
sayName(gender){
console.log(`我的名字是${this.name},${gender}`);
}
}
class Student extends Person{
constructor(name){
super(name)
}
sayName(gender){
super.sayName(gender)
}
}
var s1 = new Student('lili')
console.log(s1);
s1.sayName('hahah')
super()的含义是调用父类中的构造函数来初始化子类的变量,也就是说,每当我们要继承父类中的属性或者方法时,需要使用super()进行传参和初始化