前端JS的6种继承方法

第一种:原型链继承

利用原型链的特点进行继承

function Parent(){
   this.name = 'web前端';
   this.type = ['JS','HTML','CSS'];
}

Parent.prototype.Say = function(){
     console.log(this.name);
}

function Son(){};
Son.prototype = new Parent();
son1 = new Son();
son1.Say();

创建一个父 Parent的构造函数,里面有两个属性name、type。通过Parent构造函数的属性设置Say方法,此时,Parent有两个属性和一个方法。然后创建Son子构造函数。设置Son属性值为父构造函数Parent的实例对象,即子构造函数Son继承了父构造函数Parent,此时Son也有2个属性和1个方法。对Son构造函数进行实例化,结果赋值给变量son1,即son1为实例化对象,同样拥有2个属性和一个方法。
优点:可以实现继承。
缺点:①因为Son.prototype(即原型对象)继承了Parent实例化对象,这就导致了所有Son实例化对都一样,都共享有原型对象的属性及方法。② Son构造函数实例化对象无法进行参数的传递。

第二种:构造函数继承

通过构造函数call 方法进行继承,或者apply()调用父类型构造函数

function Parent(){
    this.name = '前端';
    this.type = ['JS','HTML','CSS'];
}

function Son(){
    Parent.call(this);
}
son1 = new Son();
son1.type.push('VUE');
console.log(son1.type);//['JS','HTML','CSS','VUE']
son2 = new Son();
console.log(son2.type);//['JS','HTML','CSS']

首先创建父级构造函数Parent,有name、type两个属性。创建子级构造函数Son,函数内部通过call 方法调用父级构造函数Parent,实现继承。分别创建构造函数Son的两个实例化对象son1,son2,对son1 的 type属性新增元素,son2没有新增。

优点: ① 实现实例化对象的的独立性;② 还可以给实例化对象添加参数。
缺点: ① 方法都在构造函数中定义,每次实例化对象都创建一遍方法,基本无法实现函数复用。②call方法仅仅调用了父级构造函数的属性及方法,没有办法调用父级构造函数原型对象的方法。

第三种:组合继承:原型链+借用构造函数(最常用)

function Parent(name){
    this.name = name;
    this.colors = ['red', 'blue', 'yellow'];
}

Parent.prototype.getName = function(){
    console.log(this.name);
}

function Child(name, age){
   // 核心代码 1
   Parent.call(this, name);

   this.age = age;
}

// 核心代码 2 子类型的原型为父类型的一个实例对象
Child.prototype = new Parent();
Child.prototype.constructor = Child;

// 可以通过子类给父类的构造函数传参
let child1 = new Child('litterStar');
let child2 = new Child('luckyStar');
child1.getName(); // litterStar
child2.getName(); // luckyStar

child1.colors.push('pink');
// 修改 child1.colors 不会影响 child2.colors
console.log(child1.colors); // [ 'red', 'blue', 'yellow', 'pink' ]
console.log(child2.colors); // [ 'red', 'blue', 'yellow' ]

注意核心代码: Parent.call(this, name);和 Child.prototype = new Parent();

融合了原型链继承和借用构造函数的饿优点,称为JavaScript种最常用的继承模式。
缺点:调用了两次父类构造函数,生成了两份实例

  • 一次是设置子类型实例的原型的时候 Child.prototype = new Parent();
  • 一次是创建子类型实例的时候 let child1 = new Child(‘litterStar’);, 调用 new 会执行 Parent.call(this, name);,此时会再次调用一次 Parent构造函数。

第四种:原型式继承 (Object.create)

借助原型可以基于现有方法来创建对象,var B = Object.create(A) 以A对象为原型,生成A对象,B继承了A的所有属性和方法。

const person = {
    name: 'star',
    colors: ['red', 'blue'],
}

// 核心代码:Object.create
const person1 = Object.create(person);
const person2= Object.create(person);

person1.name = 'litterstar';
person2.name = 'luckystar';

person1.colors.push('yellow');

console.log(person1.colors); // [ 'red', 'blue', 'yellow' ]
console.log(person2.colors); // [ 'red', 'blue', 'yellow' ]

特点: 没有严格意义上的构造函数,借助原型可以基于已有对象创建新对象
缺点:来自原型对象的所有属性被所有实例共享,person1修改 colors 会影响person2的 colors,这点跟原型链继承一样。

第五种:寄生式继承

创建一个用于封装继承过程的函数,该函数在内部以某种方式来增强对象

function createObj (original) {
    // 通过调用函数创新一个新对象
    var clone = Object.create(original);
    // 以某种方式来增强这个对象
    clone.sayName = function () {
        console.log('hi');
    }
    // 返回这个对象
    return clone;
}

缺点:每次创建对象都会创建一遍方法,跟借助构造函数模式一样。

第六种:寄生组合式继承(最理想的)

Object.create MDN上的解释:它会创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

function Parent(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'yellow'];
}
Parent.prototype.getName = function() {
    console.log(this.name)
}

function Child(name, age) {
    // 核心代码①
    Parent.call(this, name);

    this.age = age;
}
// 核心代码②
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

核心代码: Parent.call(this, name);和 Child.prototype = Object.create(Parent.prototype);
寄生组合式继承,集寄生式继承和组合式继承的优点,是引用类型最理想的继承范式。

第七种:ES6 中class的继承

ES6中引入了class关键字,可以通过extends关键字实现继承。

class Parent {}
class Child extends Parent {
    constructor(name, age, color) {
        // 调用父类的constructor(name, age)
        super(name, age);
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
    }
}

class关键字只是原型的语法糖,JavaScript继承仍然是基于原型实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值