继承

继承

一,构造函数继承(对象冒充继承)

原理:调用父类构造函数,并改变其中的this指向(bind,call,apply)局限:只继承了父类构造函数的属性,没有继承父类原型的属性

//创建一个猫的构造函数
function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.eating = function () {
        console.log('吃东西');
    }
}
Cat.prototype.shopping = function () {
    console.log('购物');
}
function Pig(){
    this.sleep=function(){
        console.log('睡觉');
    }
}
//狗类
function Dog(name, color, food) {
    this.food = food;
    //狗冒充猫,访问猫的属性或方法 (改变this指向)
    Cat.call(this, name, color);
    Pig.call(this);
}
var dog1=new Dog('大黄','黄','骨头');
console.log(dog1.name);//大黄
console.log(dog1.color);//黄
dog1.sleep();//睡觉
dog1.eating();//吃东西
dog1.shopping();//报错,无法继承父类原型上的方法

1.优点
可以继承多个构造函数的属性或方法(call多个)
在子实例中
2.缺点
只能继承父类构造函数的属性
每个新实例都有父类构造函数的副本,特别臃肿(根本原因是不能继承prototype上的属性或方法)
无法实现构造函数的复用.(每次用每次都要重新调用)

二.原型链继承

让新实例的原型等于父类的实例,实现原型链继承

//创建一个猫的构造函数
function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.eating = function () {
        console.log('吃东西');
    }
}
Cat.prototype.shopping = function () {
    console.log('购物');
}
//狗类
function Dog(name, color, food) {
    this.food = food;
}
//原型链继承
Dog.prototype=new Cat();//把狗的原型指向猫的实例对象
var dog1=new Dog('大黄','黄','骨头');
console.log(dog1.name);//undefined
console.log(dog1.color);//undefined
dog1.shopping();//睡觉
dog1.eating();//吃东西

1.优点
实例可以继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性(新实例不会继承父类实例的属性!)
2.缺点
新实例无法向父类构造函数传参
继承单一,不能实现多继承
所有新实例都会共享父类实例的属性.(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型实例属性也会被修改)

三.组合继承(常用)

原理:组合原型链继承和借用构造函数继承,结合了两种模式的优点.传参和复用(常用的一种继承方式)

//创建一个猫的构造函数
function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.eating = function () {
        console.log('吃东西');
    }
}
Cat.prototype.shopping = function () {
    console.log('购物');
}
//狗类
function Dog(name, color, food) {
    this.food = food;
    //构造函数继承
    Cat.call(this, name, color);
}
//原型链继承
Dog.prototype = new Cat();
var dog1 = new Dog('大黄', '黄', '骨头');
console.log(dog1.name);//大黄
console.log(dog1.color);//黄
dog1.shopping();//睡觉
dog1.eating();//吃东西

1.优点
可以继承父类原型上的属性,可以传参,可以复用
每个新实例引入的构造函数属性是私有的.
2.缺点
调用了两次父类构造函数(耗内存),

四.寄生组合继承(常用)

集寄生式继承和组合继承的优点与一身,是实现基于类型继承的最有效方式
比较完美的解决方式,不过就是实现复杂

// 定义一个父类动物类
function Animal(name) {
    // 属性
    this.name = name || 'Animal';
    // 实例方法
    this.sleep = function () {
        console.log(this.name + '正在睡觉!');
    }
}
// 原型方法
Animal.prototype.eat = function (food) {
    console.log(this.name + '正在吃:' + food);
};
function Cat(name) {
    Animal.call(this);
    this.name = name || 'Tom';
}
(function () {
    // 创建一个没有实例方法的类
    var Super = function () { };
    Super.prototype = Animal.prototype;//将父类的原型指向创建的类的原型
    //将实例作为子类的原型
    Cat.prototype = new Super();
    Cat.prototype.constructor = Cat; // 需要修复下子类的构造函数
})();
var cat = new Cat("大黑");
console.log(cat.name);//大黑
cat.sleep();//大黑正在睡觉!
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

1.优点
可以继承实例属性/方法,也可以继承原型属性/方法
即是子类的实例,也是父类的实例
不存在引用属性共享问题
可传参
函数可复用
2.缺点
实现起来比复杂

五.ES6 Class继承(不用想了,我就要用这个,妥妥的)

ES6继承的原理跟寄生组合式继承是一样的。但是Class是语法糖,写起来甜甜的
ES5继承与ES6继承的区别:
ES5的继承实质上是先创建子类的实例对象,再将父类的方法添加到this上。
ES6的继承是先创建父类的实例对象this,再用子类的构造函数修改this。
因为子类没有自己的this对象,所以必须先调用父类的super()方法。

class Person{
    constructor(name, age){
        this.name=name;
        this.age=age;
    }
    show(){
        alert(this.name);
        alert(this.age);
    }
}

class Worker extends Person{
    constructor(name, age, job){
        super(name, age);
        this.job=job;
    }
    showJob(){
        alert(this.job);
    }
}
let me=new Worker('jia', 18, '前端攻城狮');
me.show();//jia
me.showJob();//前端攻城狮

1.优点
原理还是参照寄生组合继承,基本原理是一样,语法糖,写起来方便,比较完美

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值