JS继承详解(原型链继承,call继承,寄生组合继承,ES6中的继承)

(来自周哥课程知识点汇总,视频链接https://www.bilibili.com/video/BV1BK41177hb)
面向对象:封装,继承,多态
多态:重载、重写
JS不存在真正意义上的重载
JS中重载指的是同一个方法,根据传参不同,实现出不同的效果

*什么是面向对象?
面向对象是一种编程思想,JS本身就是基于面向对象构建出来的(例如: JS中有很多内置类,像Promise就是ES6中新增的一个内置类,我们可以基于new Promise来创建一个实例,来管理异步编程…)

JS中的面向对象,和其它编程语言还是有略微不同的,JS中类和实例是基于原型和原型链机制来处理的;而且JS中关于类的重载重写、继承也和其它语言不太一样…

继承:子类继承父类中的属性和方法(目的是让子类的实例能够调取父类中的属性和方法)

方案一:原型继承
让父类中的属性和方法在子类实例的原型链上
CHILD.prototype = new PARENT()
CHILD.prototype.constructor = CHILD
特点:
*1.不像其他语言中的继承一样(其它语言的继承一般是拷贝继承,也就是子类继承父类,
会把父类中的属性和方法拷贝一份到子类中,供子类的实例调取使用),
它是把父类的原型放到子类实例的原型链上,实例想调取这些方法,是基于_proto__原型链查找机制完成的
*2.子类可以重写父类上的方法(这样会导致父类其它的实例也受到影响)
*3.父类中私有或者公有的属性方法,最后都会变为子类中公有的属性和方法

方案二:CALL继承的特点:
*CHILD方法中把PARENT当做普通函数执行,让PARENT中的THIS指向CHILD的实例,
相当于给CHILD的实例设置了很多私有的属性或者方法
*1.只能继承父类私有的属性或者方法(因为是把PARENT当做普通函数执行,和其原型上的属性和方法没有关系)
*2.父类私有的变为子类私有的

方案三:寄生组合继承
CALL继承+类似于原型继承Object.create(PARENT.prototype)
特点:父类私有和公有的分别是子类实例的私有和公有属性方法(推荐)

方案四:class继承
class CHILD extends PARENT

/*继承:子类继承父类中的属性和方法(目的是让子类的实例能够调取父类中的属性和方法)
方案一:原型继承
    让父类中的属性和方法在子类实例的原型链上
    CHILD.prototype = new PARENT()
    CHILD.prototype.constructor = CHILD
*特点:
*1.不像其他语言中的继承一样(其它语言的继承一般是拷贝继承,也就是子类继承父类,
    会把父类中的属性和方法拷贝一份到子类中,供子类的实例调取使用),
    它是把父类的原型放到子类实例的原型链上,实例想调取这些方法,是基于_proto__原型链查找机制完成的
*2.子类可以重写父类上的方法(这样会导致父类其它的实例也受到影响)
*3.父类中私有或者公有的属性方法,最后都会变为子类中公有的属性和方法

*/
function A(x) {
    this.x = x;
}
A.prototype.getX = function () {
    console.log(this.x);
}

function B(y) {
    this.y = y;
}

B.prototype=new A(200);  //将子类原型重定向
B.prototype.constructor=B;  //保证原型重定向后的完整性

B.prototype.getY = function () {
    console.log(this.y);
}

let b1 = new B(100) ;
b1.y; 
b1.getY();
b1.getX();  //可以调用了getX()

原型链继承
这里插入图片描述

/*
*CALL继承的特点:
*   CHILD方法中把PARENT当做普通函数执行,让PARENT中的THIS指向CHILD的实例,
    相当于给CHILD的实例设置了很多私有的属性或者方法
*1.只能继承父类私有的属性或者方法(因为是把PARENT当做普通函数执行,和其原型上的属性和方法没有关系)
*2.父类私有的变为子类私有的
*/
function A(x) {
    this.x = x;
}
A.prototype.getX = function () {
    console.log(this.x);
}

function B(y) {
    //=>this: B的实例b1
    A.call(this,200); //=>b1.x = 200  让PARENT中的THIS指向CHILD的实例
    this.y = y;
}

B.prototype.getY = function () {
    console.log(this.y);
}

let b1 = new B(100) ;
b1.y;
b1.getY();
b1.x;   //B的实例b1拥有了父类私有的x属性
/*寄生组合继承:CALL继承+类似于原型继承Object.create(PARENT.prototype)
特点:父类私有和公有的分别是子类实例的私有和公有属性方法(推荐)
*/
function A(x) {
    this.x = x;
}
A.prototype.getX = function () {
    console.log(this.x);
}

function B(y) {
    //=>this: B的实例b1
    A.call(this,200); //=>b1.x = 200  让PARENT中的THIS指向CHILD的实例
    this.y = y;
}

//=>object.create(OBJ):创建一个空对象,让空对象_proto_指向OBJ
B.prototype = Object.create(A.prototype);  //Object.create(A.prototype)仅有公有属性方法
B.prototype.constructor = B;

B.prototype.getY = function () {
    console.log(this.y);
}

let b1 = new B(100) ;
b1.y;
b1.getY();
b1.x;   //B的实例b1拥有了父类私有的x属性
b1.getX();  //B的实例b1拥有了父类公有的方法
//b1有了自己私有的100,200,还有了父类的公有的方法


//手写Object.create来解决IE不兼容__proto__属性
/*Object.create = function (obj) {
    function Fn() {}
    Fn.prototype = obj;
    return new Fn();
};
 */

寄生组合继承
在这里插入图片描述

//类
class A {
    constructor(x){
        this.x = x;
    }
    //加方法
    getX() {
        console.log(this.x);
    }
}
//加属性方式
A.prototype.num=10;
//A()报错,不能当作普通函数执行,即call继承不能在次使用

class B extends A{
    //子类只要继承父类,可以不写CONSTRUCTOR,一旦写了,
    //则在CONSTRUCTOR中的第一句话必须是SUPER()
    //不写CONSTRUCTOR,浏览器会自己默认创建
    //CONSTRUCTOR(...args){ super(...args) }
    constructor(y){
        //A.call(this,200)
        //Class constructor A cannot be invoked without 'new'
        super(200);//super与constructor同在 =>A.call(this,200)
        //super把父类当做普通方法执行,给方法传递参数,让方法中的THIS是子类的实例
        this.y = y;
    }
    //加方法
    getY() {
        console.log(this.y);
    }
}

//B.prototype = Object.create(A.prototype); 
//不允许重定向原型的指向
let b1 = new B(100);
console.log(b1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值