JavaScript ES5继承

前言

在ES6中,继承是依靠类来实现的,但是在ES5中,实现继承的方式依靠原型链完成,相对于ES6比较复杂一点,先来看看ES6中的继承的写法

ES6的类的写法
在ES6的中,子类可以继承父类的方法和属性,这里的父类(确切来说是超类)为Box,子类Ball继承父类Box的方法和属性,必须在构造函数constructor中写super()才可以继承

class Box{
            constructor(){

            }
            play(){

            }
        }
class Ball extends Box{
    constructor(){
        super();
    }
}

es5的类的写法

function Box(_r){
    this.r=_r;
    console.log("aa");
}

Box.a=3;//相当于es6中的静态属性
Box.run=function(){
    console.log(Box.a);//相当于es6的静态方法
}

Box.prototype.b=10;//相当于es6中的动态属性
Box.prototype.play=function(){//相当于es6中的动态方法
    console.log(this.b);
}
var b=new Box(3);
console.log(b)  //{r:3,__proto__:{b:10,play:f(),constructor:f(),__proto:{}}}

在这里插入图片描述
如果设置原型属性和方法时,以对象的形式写的话,就会覆盖掉原本的原型链,这样就会少了constructor

function Box(_r){
    this.r=_r;
    console.log("aa");
}

Box.a=3;
Box.run=function(){
    console.log(Box.a);
}

Box.prototype={
	b:10,
	play:function(){
	   console.log(this.b);
	}
}

Box.prototype.b=10;
Box.prototype.play=function(){
    console.log(this.b);
}
var b=new Box(3);
console.log(b)  //{r:3,__proto__:{b:10,play:f(),__proto:{}}};  //少了constructor
	}}}

在这里插入图片描述
如果以对象的形式写,并且不会覆盖原有的__proto__,则需要重新定义constructor为当前类的构造函数,并且这个构造函数不可以修改,不可以遍历,不可以删除

  • 如果是基类,可以直接这样写,但是后面还必须重新定义constructor为当前类的构造函数
  • 如果不是基类,就不能直接使用prototype重设置对象
function Box(_r){
    this.r=_r;
    console.log("aa");
}

Box.a=3;
Box.run=function(){
    console.log(Box.a);
}
Box.prototype={
    b:10,
    play:function(){

    }
}
Object.defineProperty(Box.prototype,"constructor",{
    value:Box
})

var b=new Box(3);
console.log(b);

ES5继承

1、组合式继承,把父类的实例化对象放在子类的原型下

超类的构造函数被执行两遍,这种继承适合于超类的构造函数中没有任何语句
new Box(3)执行一遍Box构造函数,Box.call(this,_r)又执行一遍

function Box(_r) {
    this.r = _r;
    console.log("aa");
}
Box.a = 3;
Box.run = function () {
    console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
    console.log(this.b);
}


function Ball(_r){
	//冒充
	 Box.call(this,_r);//执行Box构造函数 把Box里的this替换成Ball的this,这叫冒充
}
Ball.prototype=new Box(3);//new Box(3)是实例化对象    Ball.prototype是子类的原型
var c=new Ball(10);
console.log(c);

在这里插入图片描述

2、原型继承

这种方式就不用执行两遍超类的构造函数,但是一遍都没执行,只完成了原型的继承
将Box的原型赋值给F的原型,F类没有Box的构造函数

function Box(_r) {
    this.r = _r;
    console.log("aa");
}
Box.a = 3;
Box.run = function () {
    console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
    console.log(this.b);
}

function F(){
}
F.prototype=Box.prototype;

function Ball(){

}
Ball.prototype=new F();
var b=new Ball();
console.log(b);

在这里插入图片描述

3、Object.create

这种继承写法只能用于IE9以上浏览器,这种继承写法中,执行一遍超类的构造函数,也完成了原型的继承。

function Box(_r) {
    this.r = _r;
    console.log("aa");
}
Box.a = 3;
Box.run = function () {
    console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
    console.log(this.b);
}

function Ball(_r){
    Box.call(this,_r)
}
Ball.prototype=Object.create(Box.prototype);

var b=new Ball(10);
console.log(b);

在这里插入图片描述

4、寄生式继承
function Box(_r) {
    this.r = _r;
    console.log("aa");
}
Box.a = 3;
Box.run = function () {
    console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
    console.log(this.b);
}

function Ball(_r){
    // super();
   this.superClass.apply(this,arguments);
}
Ball.prototype.walk=function(){
    console.log("walk");
}
extend(Ball,Box);

Ball.prototype.play=function(){
    // super.play();
    this.superClass.prototype.play.apply(this,arguments);
    console.log("执行完成")
}

var b=new Ball(10);
// console.log(b);
b.play();

function extend(subClass,supClass){
    function F(){}
    F.prototype=supClass.prototype;
    // subClass.prototype=new F();
    // Object.assign(subClass.prototype,new F());
    var o=subClass.prototype;
    subClass.prototype=new F();
    // 复制原来的原型下的所有内容
    if(Object.assign){
        // 如果Object.assign可以使用时
        Object.assign(subClass.prototype,o);
    }else{
        // Object.getOwnPropertyNames可以使用时
        if(Object.getOwnPropertyNames){
            var names=Object.getOwnPropertyNames(o);
            for(var i=0;i<names.length;i++){
                Object.defineProperty(subClass.prototype,names[i],Object.getOwnPropertyDescriptor(names[i]));
            }
        }else{
            for(var prop in o){
                subClass.prototype[prop]=o[prop]
            }
        }
    }
    subClass.prototype.constructor=subClass;
    subClass.prototype.superClass=supClass
    if(supClass.prototype.constructor===Object){
        supClass.prototype.constructor=supClass;
    }

}

可以直接封装

function Ball(_r){
        // super();
       this.superClass.apply(this,arguments);
    }
    Ball.prototype.walk=function(){
        console.log("walk");
    }
    
    Ball.extend_1(Box);

    Ball.prototype.play=function(){
        this.superClass.prototype.play.apply(this,arguments);
        console.log("执行完成")
    }

    var b=new Ball(10);
    b.play(); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

胡肖一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值