发表于: 2019-12-04 23:11:21

1 1264


今天完成的事:

复习

明天计划的事:

复习

遇到的问题:

暂无

收获:

关于继承的实现和优缺点整理

一、什么是继承

一个类获取另一个或者多个类的属性或者方法。继承可以使得子类具有父类的各种方法和属性。以免重复输出很多代码。

二、继承的原理

复制父类的方法和属性来重写子类的原型对象。

三、原型链继承

1、实现

function Father() {
    this.text = '1';
}
Father.prototype.someFn = function() {
    console.log(1);
}
Father.prototype.someValue = '2';

function Son(){
    this.text1 = 'text1';
}
// 函数原型指向构造函数的实例
Son.prototype = new Father();

2 优点

1、简单易操作。

3 缺点

1、父类使用this声明的属性被所有实例共享。 原因是实例化是父类一次性赋值到子类实例的原型上,它会将父类通过this声明的属性也赋值到子类原型上。例如在父类中一个数组值,在子类的多个实例中,无论哪一个实例去修改这个数组的值,都会影响到其他子类实例。
2、创建子类实例时,无法向父类构造函数传参,不够灵活。

四、借用构造函数(call)

1、实现

function Father(...arr) {
this.some = '父类属性';
this.params = arr;
}
Father.prototype.someFn = function() {
console.log(1);
}
Father.prototype.someValue = '2';
function Son(fatherParams...sonParams) {
// Father的this指向Son的this
// 使用call调用父类,Father将会立即被执行,并且将父类的Father的this执行Son
// 的this。实例化子类,this将指向new期间创建的新对象,返回该新对象。
Father.call(this...fatherParams);
this.text = '子类属性';
this.sonParams = sonParams;
}
var fatherParams = [];
var sonParams = [];
var sonInstance = new Son(fatherParams, ...sonParams);

2 优点

1、可以向父类传递参数。
2、解决父类this声明的属性会被实例共享的问题。

3 缺点

1、只能继承父类通过this声明的属性/方法。不能继承父类prototype上的属性/方法。
2、父类方法无法复用。每次实例化子类,都要执行父类函数。重新声明父类所定义的方法,无法复用。

五、组合继承(call+new)

原理:通过原型链继承来将this、prototype上的属性和方法继承制子类的原型对象上。使用借用构造函数来继承父类通过this声明的属性和方法在之子类的实例属性上。

1、实现

function Father(...arr) {
this.some = '父类属性';
this.params = arr;
}
Father.prototype.someFn = function() {
console.log(1);
}
Father.prototype.someValue = '2';
function Son(fatherParams...sonParams) {
// 借用构造函数继承父类this什么的属性和方法到子类实例属性上
Father.call(this...fatherParams);
this.text = '子类属性';
this.sonParams = sonParams;
}
// 原型链继承,将`this`和`prototype`声明的属性/方法继承至子类的`prototype`上
Son.prototype = new Father('xxxxx');
var fatherParams = [];
var sonParams = [];
var sonInstance = new Son(fatherParams, ...sonParams);

2 优点

1、解决原型链继承父类this声明的属性或者方法被共享的问题。
2、解决借用构造函数解决不能继承父类prototype对象上的属性/方法问题。

3 缺点

1、调用了父类函数两次,造成一定的性能问题。
2、因调用两次父类,导出父类通过this声明的属性和方法被生成两份的问题。
3、原型链上下文丢失,子类和父类通过prototype声明的属性和方法都存在与子类prototype上。

六、原型式继承

1、实现

function cloneObj(obj) {
function F(){};
// 将被继承的对象作为空函数的prototype
F.prototype = obj;
// 返回new期间创建的新对象,此对象的原型为被继承的对象,
// 通过原型链查找可以拿到被继承对象的属性
return new F();
}

2 优点

1、兼容性好,最简单的对象继承。

3 缺点

1、多少实例共享被继承的属性,存在被篡改的情况,不能传递参数。

七、寄生式继承(继承过程封装)

创建一个仅用于封装继承过程的函数,改函数在内部已某种方式类增强对象,最后返回对象。在原型式继承的基础上进行增强对象。

1、实现

function createAnother(original){
var clone = cloneObject(original); // 继承一个对象 返回新函数
// do something 以某种方式来增强对象
clone.some = function(){}; // 方法
clone.obkoro1 = '封装继承过程'// 属性
return clone; // 返回这个对象
}

2 优点

1、兼容性好,最简单的对象继承。

3 缺点

1、多少实例共享被继承的属性,存在被篡改的情况,不能传递参数。

八、寄生组合式继承(call+寄生式封装)

1、使用借用构造函数来继承父类this声明的属性和方法。 2、使用寄生式继承来设置父类prototype为子类prototype的原型来继承父类的属性和方法。

1、实现

function Father(...arr) {
this.some = '父类属性';
this.params = arr;
}
Father.prototype.someFn = function() {
console.log(1);
}
Father.prototype.someValue = '2';
function Son() {
Father.call(this'xxxx');
this.text = '2222';
}
function inhertPro(sonfather){
// 原型式继承
var fatherPrototype = Object.create(father.prototype);
// 设置Son.prototype的原型是Father.prototype
son.prototype = fatherPrototype;
// 修正constructor 指向
// constructor的作用:返回创建实例对象的Object构造函数的引用。
// 在这里保持constructor指向的一致性
son.prototype.constructor = son;
}
inhertPro(Son, Father);
var sonInstance = new Son();

2 优点

1、寄生组合式继承是当前最成熟的继承方法,也是先也常用的继承方法,在大多数Js框架中都是用这个作为继承方案。
寄生组合式继承相对组合继承的优点:
1、只调用了父类构造函数一次,节约了性能。
2、避免生成了不必要的属性。
3、使用原型式继承保证了原型链上下文不变,子类的prototype只有子类通过prototype声明的属性和方法,父类的prototype只有父类通过prototype声明的属性和方法。




返回列表 返回列表
评论

    分享到