什么是继承
继承就是一个构造函数,想要将另一个构造函数的所有属性和方法,以及其原型链中的属性和方法归为己用。
继承的几种常用方式
1、原型链继承
原型链继承就是将想要继承的构造函数的实例化对象替换自己的原型对象。如下代码
function Foo(){
this.name = 'li';
this.age = 13;
this.say = function(){
console.log('hello world');
}
}
Foo.prototype.sex = '男';
function Foo1(){
this.name = 'wu'
}
Foo1.prototype = new Foo();
var f1 = new Foo();
var f2 = new Foo1();
console.log(f2,f2.age,f2.sex);//Foo { name: 'wu' } 13 男
从上述代码中可以看出,Foo1成功继承了Foo中的属性和方法以及其原型链中的属性和方法。
但上述方法存在一些不足:
- 新实例无法向父类构造函数传参。
- 只能继承一个父类
- 所有新实例都共享父类实例的属性。
2、借用构造函数继承
其实原理就是借助call/apply的自动执行特点,示例代码如下
function Foo(name){
this.name = name;
this.age = 13;
this.say = function(){
console.log('hello world');
}
}
function Foo2(){
this.run = "I can run"
}
Foo.prototype.sex = '男';
function Foo1(){
this.name = 'wu';
Foo2.call(this);
Foo.call(this,'huang');
}
var f1 = new Foo1();
console.log(f1.name);//huang
console.log(f1.run);//I can run
从上面可以看出,使用call的方法可以,继承不同的父级的构造函数中的属性和方法,也可以实现给父级中传值。
但同样存在一些不足:
- 不能继承父级的原型链中的方法
- 方法是在构造函数中直接执行的,无法实现复用
3、组合继承(常用)
继承父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用。
function Foo(name){
this.name = name;
this.age = 13;
this.say = function(){
console.log('hello world');
}
}
Foo.prototype.sex = '男';
function Foo1(){
this.name = 'wu';
Foo.call(this,'huang');
}
Foo1.prototype = new Foo();
var f1 = new Foo1();
console.log(f1.age);//13
console.log(f1.name);//huang
组合继承,即可以继承父类的原型链上的方法和属性,也可以继承本身的方法属性,可以进行传值,可以复用。 不足是调用了两次父级的构造函数浪费内存。
ES6应用class
在ES6中引入了一个新的class概念,通过extends来继承父类,class中有一个constructor方法,可以传私有变量,在其中可以定义一个super()方法,用来实现对父类的继承。
class Foo{
constructor(name='wang',age='13'){
this.name = name;
this.age = age;
}
eat(){
console.log(`${this.name} ${this.age} eat food`)
}
}
//继承父类
class Foo1 extends Foo{
constructor(name = 'li',age = '14'){
//继承父类属性
super(name, age);
}
eat(){
//继承父类方法
super.eat()
}
}
let f1 = new Foo1('yu');
f1.eat();