JavaScript的继承实现详解

JavaScript的继承实现详解

此文章共提及六种JavaScript中的继承实现方式
第一种:原型链继承
原型链继承是一种很常见的继承方式其中涉及了构造函数、原型和实例
首先我们需要了解在原型链中有三种属性分别是:__ proto__,prototype,construct.我们所需要了解的就是这三个属性之间的关系和他们各自的作用这样就了解了原型对象,进而了解原型链的继承方式。
首先我们先了解__ proto__:每一个对象在被创造出来的时候会自带一个__ proto__属性,这个属性被称为原型链对象,也就是所谓的隐式原型,是一个引用类型数据,而这个对象被创造出来之后会默认指向那个把__ proto__属性创造出来的构造函数原型中的prototype属性,那么这个被天生带出来的__ proto__有什么作用呢?,它的作用就是找到它的父级,保证实例化的对象能够访问到在构造函数原型属性中所定义的属性和方法。
看完上面的解释你可能又对构造函数和实例和原型之间的关系不清楚了,**构造函数new出了实例,而实例通过__ proto__引用属性指向了原型,原型constructor构造函数,构造函数prototype原型,最后实例又constrctor构造函数,**这既是他们之间的关系,大家可以自己动手画个三角形的图来加强理解
那么对于prototype的属性和__ proto__就没什么差别了,实例对象通过__ proto__访问原型对象,而函数对象通过prototype来访问原型对象,然后实例对象通过constructor属性可以访问到构造函数,因为constructor属性可以访问到构造函数,原型对象上面的constructor属性跟实例对象一样,都是指向其构造函数
这里详细的解释一下原型链:
 原型链:

对象可以通过“.”操作获取到一个属性的值,首先会在对象自身开始查找,如果查不到会到原型对象(proto)中去查找,如果原型对象中还没有就会把当前得到的原型对象当作实例对象,继续通过(proto)去查找当前原型对象的原型对象中去找,也就是去爸爸的爸爸那里找,直到__proto__为null时停止;

上面可能有点不太好理解,我们换个生活中的例子来理解:就是你有个对象,你丈母娘问你要20W彩礼,你自己拿不出来你没有(对象本身没有属性),丈母娘让你问你爸爸(原型对象)要,如果你爸爸也没有,你爸爸就得问你爸爸的爸爸也就是你爷爷要(原型对象的原型对象,这里的第一个原型对象实质上成了一个实例对象,因为你爸爸在你爷爷那里永远是儿子),如果你爷爷也没有就继续往上要……如此反复,实在拿不出来(null),丈母娘大手一挥,拿不出来就不嫁了(直到为null时停止);
    以上就是对原型链的全部解释。
    一下是对原型链继承的简易解释:
    原型链实现继承:

我们知道所有的对象都有个toString()方法,上述代码中实例对象xianyu其实也是一个对象,这就是JS中的万物皆对象的道理,我们没有给xianyu加任何toString()方法,它是哪里来的?继承来的!因为xianyu.__proto__最终指向的是Function原型对象(Function函数对象一直往上查找原型对象最终是Function原型对象,Object函数对象一直往上查找原型对象最终是null),因为Function原型对象中有,所以xianyu作为它的实例会继承上面的方法,这就是JS继承的本质;
    也就是说你爹(原型对象)那有20W,没花在银行存着,你(实例对象)也可以理解为你有20W在银行存着,因为你爹的钱迟早会给你,你爹的钱间接就是你的钱,你要是还存着,你的儿子(实例对象的实例对象)也就间接有了20W;
    第二种:构造函数继承(借助call实现)
    其实也不一定非要使用call,apply也可以达到同样的效果,一般的实现情况:在子类的实例环境下使用call来调用父类的构造函数,这样之后在子类的函数中也有了父类所有对象的初始化代码,这样子类就有了属于自己的属性了。
    不过这样的方法也是有一定的弊端的,方法都在构造函数中定义,因此函数的复用就无从谈起了。而且在父类型的原型中定义的方法,对子类型而言是不可见的。因此所有类型都只能使用构造函数模式。一般情况下不建议单独使用借用构造函数技术。
    第三种组合继承(将上述的两种方法杂糅在一起实现)
它的实现思路是这样的:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,即通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。
用图片的形式展示:
在这里插入图片描述

第四种原型式继承
对于原型式的继承有两种实现方法:1.使用嵌套构造函数的方式
2.使用Object.create()方法
对于第一种的实现方式:父级对象obj,设置一个对象result用来新增属性和方法,函数fn负责将新增的属性和方法遍历到obj里从而完成子对象对obj的继承。大家可以思考一下如何代码实现。
第二种方法的实现:依然是使用obj作为父级对象,通过该方法向obj里新增属性方法并转化为一个新对象输出。
第二种方法实现代码如下

// 利用Object.create()方法实现继承
var obj={
    name:'我爱罗'
}
var newObj=Object.create(obj,{
    age:{
        value:18
    },
    sayMe:{
        value:function(){
            console.log('this is function');
        }
    }
});
console.log(newObj.age);
newObj.sayMe();

第5种方式:寄生式继承
使用原型式继承可以获得目标对象的浅拷贝然后利用这个浅拷贝的能力在进行增强(添加一些方法),简单来说就是寄生式继承就是把原型式继承再次封装,然后在对象上扩展新的方法,再把新对象返回。这里就不详细说明了
第六种方式:寄生组合式继承:
在前几种继承方式上进行改造,应该是目前最优的继承方式
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。
具体的代码实现:

function inheritPrototype(subType, superType){
     var prototype = object(superType.prototype);     //创建对象     
     prototype.constructor = subType;              //增强对象     
     subType.prototype = prototype;               //指定对象 
     } 

总结:
在这里插入图片描述
上述总结图片来自拉勾教育。如果文章有问题或者想讨论技术的或者想找作者聊人生的可以+QQ:2029788643

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值