最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript中的继承

    正文概述 掘金(Joe_cat)   2021-01-28   621

    前言

    提起继承我们最开始想到了应该是子类继承父类,接下来尽量用简洁的语言来表达清楚什么是继承

    正文

    原型继承

    什么是原型继承

    function Parent(){
    	this.dd = 'qq';
    }
    Parent.prototype.getDd = function(){
    	return this.dd
    }
    
    function Child(){
    	this.name = 'qq';
    }
    
    Child.prototype.getName = function(){
    	return this.name
    }
    let child = new Child;
    

    此时思考一下child能获取或调用哪些方法或属性?答案肯定是可以获取name属性,以及可调用getName方法,所以我们能够发现,child实例可调用自己Child类私有的以及Child类原型prototype上公有的方法

    那么此时我们想让child继承父类Parent的属性,我们只需要将Child.prototype=new Parent,因为new ParentParent的实例,可以调用自己类私有以及类原型上的公有方法。这样我们便达到了原型继承的目的。

    function Parent(){
    	this.dd = 'qq';
    }
    Parent.prototype.getDd = function(){
    	return this.dd
    }
    function Child(){
    	this.name = 'qq';
    }
    Child.prototype = new Parent;
    Child.prototype.getName = function(){
    	return this.name
    }
    let child = new Child;
    

    这样我们创建的实例child便可以调用getDd以及child.dd,但是我们也要注意代码添加的位置,如果我们在倒数第二行添加,则会导致getName属性消失。

    接下来我们在控制台输出child,打印结果如下图,可能你会对打印结果存在疑惑,为什么是这样一层一层包下去的呢?接下来我们解释一下结果的产生:

    JavaScript中的继承

    原型链如下图所示,我们能够看到蓝色的①②③,这就是执行时原型链的查找顺序:

    • 首先在①处,存在属性name: 'qq'

    • 接下来按照②child.__proto__方向进行查找,找到属性dd: 'qq', getName: function ...

    • 继续按照③new Parent.__proto__方向查找,找到Parent.prototype里面的属性constructor, getDd

    • ...

    JavaScript中的继承

    这就是child的结果的产生。

    总结

    • 父类中私有和公有的属性方法,最后都变为子类实例公有的

    • 和其他语言不同的是,原型继承并不会把父类的属性方法【拷贝】给子类,而是让子类实例基于__proto__ 原型链找到定义的属性和方法,"指向/查找"方式的

    • 在上面的实例child中,通过child.__proto__.xxx = xxx来修改子类原型(原有父类的一个实例)中的内容,内容被修改后,对子类的其他实例有影响,但是对父类的其他实例不会有影响

    • 通过child.__proto__.__proto__.xxx = xxx直接修改的使父类原型,这样不仅会影响父类的其他的实例,也会影响其他子类的实例

    CALL继承

    什么是原型继承

    对于call我们能够想到的是改变this指向,并且最常见的使用是A.call(B),将A执行,并强制将this改变为B,所以接下来也将使用这种方式来理解CALL继承。

    首先我们要先明白一件事,在类中this指向的是实例,也就是说在Childthis为实例child,所以执行的this.name是在实例child上添加私有属性。所以我们看下面的代码:

    function Parent(){
        this.dd = 'qq';
    }
    Parent.prototype.getDd = function(){
        return this.dd
    }
    
    function Child(){
        Parent.call(this);
        this.name = 'qq';
    }
    
    Child.prototype.getName = function(){
        return this.name
    }
    let child = new Child;
    

    我们添加了 Parent.call(this);这样一行代码,在子类中调用父类执行并强制将Parent中的this修改为子类的实例对象child,此时Parent执行时this.dd = 'qq'相当于给实例child上添加属性dd.相当于让子类的实例继承了父类的私有的属性,并且也变为了为子类私有的属性"拷贝式"

    JavaScript中的继承

    总结

    CALL继承只能继承父类中私有的,不能继承父类中公共的

    寄生组合继承(CALL继承 + 另类原型继承)

    根据上面的两种继承,第一种实现了将父类的私有以及公有属性都继承了,对于子类实例讲,父类的私有属性却变成了公有有。第二种便只能实现私有属性的继承,将父类的私有属性变为子类实例的私有属性。而我们最想要的是:将父类的私有属性,变为子类的私有属性(这个使用CALL继承已经实现),将父类的公有属性,变为子类实例的公有属性。

    实现思路:在CALL继承的基础上实现将父类的共有属性,变为子类实例的公有属性

    JavaScript中的继承

    上图为CALL继承的原型链,我们能够发现现在只需要对Child.prototype.__proto__Parent.prototype之间建立连接就可以实现,所以我们的完整代码为:

    function Parent(){
    	this.dd = 'qq';
    }
    Parent.prototype.getDd = function(){
    	return this.dd
    }
    
    function Child(){
        Parent.call(this);
    	this.name = 'qq';
    }
    Child.prototype.__proto__ = Parent.prototype
    
    Child.prototype.getName = function(){
    	return this.name
    }
    let child = new Child;
    

    JavaScript中的继承

    根据上图说明我们的效果已经实现了,但是由于在低版本浏览器中对__proto__的兼容性不好,所以我们在进行优化一下:

    function Parent(){
    	this.dd = 'qq';
    }
    Parent.prototype.getDd = function(){
    	return this.dd
    }
    
    function Child(){
        Parent.call(this);
    	this.name = 'qq';
    }
    Child.prototype = Object.create(Parent.prototype)
    Child.prototype.constructor = Child;
    Child.prototype.getName = function(){
    	return this.name
    }
    let child = new Child;
    

    说明:我们将Child.prototype的指向改变了,可以将Object.create(Parent.prototype)理解为创建了一个空对象,然后将这个空对象.__proto__指向了Parent.prototype,但是这时候子类的原型上丢失了constructor属性,所以我们手动添加此属性,保存完整性。所以实现了将父类的共有属性,变为子类实例的公有属性。

    ES6中的类和继承

    class Parent {
        constructor(){
            this.x = 100; 
        }
        getX(){
            return this.x
        }
    }
    
    class Child {
        constructor(){
            this.y = 100; 
        }
        getY(){
            return this.y
        }
    }
    let c1 = new Child;
    

    说明:

    • ES6中,通过class创建类,其中constructor相当于类原型上的constructorgetX相当于在类的原型上添加属性。

    • 想要实现继承需要在上面的例子中添加以下代码

      class Child extends Parent{
        constructor(){
            super();
            this.y = 100; 
        }
        getY(){
            return this.y
        }
      }
      

      ①. extends表示继承,后面的表示Parent继承谁的属性。

      ②. 当使用继承时一定要在constructor中加入super,相当于我们之前的CALL继承,super执行就等同于把Parent中的constructor执行

      JavaScript中的继承

    最后

    biu biu biu ~ ❤️❤️❤️❤️ 点关注 ?? 不迷路 点个赞哦?


    起源地下载网 » JavaScript中的继承

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元