前端一般来说现在有7种继承方式:
1.原型链继承、2.构造函数继承、3.原型式继承、4.寄生继承、5.组合继承、6.寄生组合继承、7.extends类继承
1.原型链继承
核心:子类的 原型 是父类的一个 实例对象
//父类
function parent(){
this.name="张三"
}
//子类
function child(){
this.age=18
}
//子类的原型 prototype 是父类的一个实例对象;这里已经实现子类对父类的继承
child.prototype=new parent()
//实例化子类
let person=new child()
//person使用父类的属性 name
console.log(person.name)//"张三"
优点:继承容易实现,比较好理解,可以继承父类所有的属性和方法
缺点:不能实现多继承,不能向父类传递参数
2.构造函数继承
核心:用call()方法改变this指向,子类把父类当作普通函数调用
//父类
function parent(name){
this.name=name
}
//父类原型方法
parent.prototype.say=function(){
console.log("说话")
}
//子类
function child(name){
parent.call(this,name)//相当于this.parent()
//parent.apply(this,name)//效果与call()方法一样
}
//实例化子类
let person=new child("张三")
//person使用父类的属性 name
console.log(person.name)//"张三"
//但是person不能使用父类的原型上的属性
person.say()//undifined
优点:可以向父类传递参数,可以通过call或apply多个父类对象实现多继承
缺点:只能继承父类的实例属性和方法,不能继承原型上属性和方法
3.原型式继承
核心:父对象直接创建子对象,使用object.create() 实现继承
//父对象
let parent={
arr:["张三","李四"]
}
//创建子对象
let child=Object.create(parent);
//子对象使用父对象的属性
console.log(child.arr)//"张三","李四"
child.arr.push("王五")
//创建新的子对象
let newChild=Object.create(parent);
console.log(newChild.arr)//"张三","李四","王五"
//每个子对象都共用一个父对象,父对象的属性发生变化会影响所有的子对象
优点:可以继承父对象所有的属性和方法
缺点:所有的子对象都公用一个父对象
4.寄生继承
核心:原型式继承 + 添加子类方法
function createObj(obj) {
//原型式继承
let clone = Object.create(obj);
clone.say = function() {
console.log("你好");
}
return clone;
}
//父对象
let parent = {
name: "张三",
sayHello: function() {
console.log('Hello');
}
};
let child = createObj(parent);
console.log(child.name); // "张三"
child.sayHello(); // Hello
child.say(); // "你好"
优点:在原型式继承优点的基础上 还可以在父类基础上添加更多的方法
缺点:所有的子对象都公用一个父对象
5.组合继承
核心:原型链继承+构造函数继承
//父函数
function parent(name) {
this.name = name;
}
//父函数原型方法
parent.prototype.say = function() {
console.log("你好");
}
//子函数
function child(name, age) {
//构造函数继承
parent.call(this, name);
this.age = age;
}
//原型链继承
child.prototype = new parent();
//实例化对象
let person= new child("张三", 18);
console.log(person.name); // "张三"
console.log(person.age); // 18
person.say(); // "你好"
优点:既可以使用父函数的实例属性和方法又可以使用父函数的原型链属性和方法
缺点:调用两次父函数
6.寄生组合继承
核心:避免两次调用父类构造函数,通过赋值直接继承父类的原型
//寄生组合继承函数
function clone (parent, child) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
}
//父函数
function parent() {
this.name = "张三";
}
//父函数原型方法
parent.prototype.getName = function () {
return this.name;
}
//子函数
function child() {
parent.call(this);
this.friends = "李四";
}
//子函数原型方法
child.prototype.getFriends = function () {
return this.friends;
}
//调用继承函数
clone(parent, child);
//实例化对象
let person = new child();
console.log(person.getName());//"张三"
console.log(person.getFriends());"李四"
优点:可以解决组合继承会调用两次父类的构造函数,造成浪费的问题 ,比较完美,实际开发使用最多
7.extends类继承
核心:使用es6提出的关键字 extends进行继承
//父类
class parent{
constructor (name,age) {
this.name = name
this.age = age
}
say() { console.log("你好") }
}
//子类
class child extends parent{
constructor (name,age,sex) {
super(name, age);
this.sex=sex
}
sayHello(){consle.log("hello")}
}
//实例化对象
let person=new child("张三","18","男");
console.log(person.say())//"你好"
console.log(person.sayHello())//"hello"
console.log(person.name))//"张三"