1.原型链继承
原理: 通过修改子构造函数的原形对象,使其指向一个父构造函数的实例。这样 子类的实例可以通过原型链访问到父类的属性和方法;
优势:实现简单,代码简洁;
劣势:不能向父类构造函数传递参数 ,且所有子类实例共享父类的引用类型属性,修改其中一个会影响所有实例;
实例代码
js
function Parent(name){
this.name = name;
}
Parent.prototype.sayHello = ()=>{
console.log('hello,'+this.name);
}
function Child(){
//业务逻辑
//不能向父类传递参数
}
Child.prototype = New Parent();
var child = New Child();
child.sayHello(); //输出: hello, underiend --因为new Parent()为传参;
2.借用构造函数继承
原理: 在子类构造函数中调用父类构造函数,实现参数传递。
优势: 每个子类实例都有自己独立的属性,不会共享引用类型属性。
劣势: 方法不能复用,每次创建子类实例时都会重新执行父类构造函数。
示例代码:
js
function Parent(name){
this.name = name;
}
Parent.prototype.sayHello = ()=>{
console.log('hello,'+this.name);
}
function Child(name,grade){
//call 方法允许你调用一个函数,并且可以指定函数执行时this值;
Parent.call(this.name) //调用父类构造函数传递参数;
this.grade = grade;
}
var child = new Child('Alice', 10)
child.sayHello(); //输出: hello, Alice
3.组合继承
即:借用构造函数继承 + 原型链继承
原理:通过借用构造函数继承属性、传递参数,又通过原型链继承父类方法;
优势:结合了原型链继承和方法复用的优点,每个实例有单独的属性(借用构造函数继承优势),方法可以复用;
劣势:父类构造函数会执行2次,效率较低;
示例代码:
js
function Parent(name){
this.name = name;
}
Parent.prototype.sayHello = ()=>{
console.log('hello,'+this.name);
}
function Child(Name, grade){
Parent.call(this, name) //借用构造函数继承属性
this.grade = grade;
}
Child.prototype = Object.create(Parent.prototype); // 原型链继承方法
Child.prototype.constructor = Child; //修正构造函数的指针
var child = new Child('Alice',10)
child.sayHello(); //输出: hello, Alice
4.原型式继承
记住是原型式继承,不是原型链继承,就差一个字
原型式继承(Object.create)
使用Object.create()方法创建一个对象,其原型指向一个已存在的对象。
js
const person = {
name: "John",
greet: function(){
console.log(`Hello, my name is ${this.name}`);
}
}
const john = Object.create(person); //以person为原型创建john对象
john.name = 'jonny'; //修改join的属性,不影响person对象的其他实例或原型链上的属性;
john.greet(); //Hello,my name is jonny;
5.寄生式继承(一种特殊的原型式继承)
创建一个函数,这个函数以某种方式增加对象,然后返回这个对象。通常用于在不改变默认函数的情况下增加。
js
function createPerson(original){
const clone = Object.create(original); //通过原型式继承基本对象的功能
clone.greet = function(){ //新增方法或属性到克隆对象上
console.log(`Hello, my name is ${this.name}`);
}
return clone; //返回克隆对象,增强了功能版本的对象。
}
6.寄生组合式继承
结合了借用构造函数和原型链继承的优点,通过借用构造函数传递实例属性,通过修改原型链实现方法的共享,同时避免了组合继承中子类构造函数被调用两次的缺点。
js
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;
}
// 寄生组合式继承的关键部分
(function() {
// 创建一个没有实例方法的对象或"窃取"函数
var Super = function() {};
Super.prototype = Parent.prototype; // 继承Parent的原型方法
Child.prototype = new Super(); // 实例化Super,并将其赋值给Child的原型
Child.prototype.constructor = Child; // 修正构造函数指向
})();