JS中写继承的方式

有父子两个函数,代表两个类:

var parent = function(){}
var child = function(){}

一、直接继承

child.prototype = new parent();
child.prototype.constructor = child;

这种方式有风险,说是如果parent中有this,然后parent在其他地方给this混入了其他东西,child的继承原型中就会莫名多了其他不属于他们的东西,这样不好。。。

-----------------

2020.04.24,来针对上面这种继承方式的风险进行说明。

假设parent的构造函数中包含了很多属性,其中包括引用类型的,也就是这样的:

function Parent(name,age){
    this.name=name
    this.age=age
    this.arr=[]
    this.obj={}
}

  其中arr和obj就是风险,如果设置child.prototype=new Parent(name,age),child.prototype.constructor=child,那么接下来child的所有实例化对象都会包含这两个arr,obj,并且引用地址都是同一个,那么问题就来了,假设有两个Child的实例化对象,var child1=new Child(),var child2=new Child(),如果child1.arr.push(xxxx),或者child1.obj.xxx=xxxx,那么完蛋了,child2拿到的arr和obj都会受到影响,拿到的都是受到影响之后的对象。

化解这种风险的方法:也可以在Child的构造函数中,写自己的特有的属性之前调用一下Parent.call(this),这样就可以将父类的属性变成自己的属性了,而不再是共享在原型中的了,这样操作以后,哪怕再写Child.prototype=new Parent()也不怕了,因为继承关系,子类属性已经在了,哪怕原型中有同名属性也不怕。那么就怕使用delete之后再改原型对应的属性,那么还是有风险【捂脸】。

而下面的借助中间空函数的做法,就能完全避免这种问题,因为空函数本身不引入任何this的东西。

-----------------

二、借助中间空函数

var nop = function(){}
nop.prototype = parent.prototype;
child.prototype = new nop();
child.prototype.constructor = child;

空函数的办法,就解决了第一种方法的隐患,空函数中没有任何this相关的隐患,如果封装在一个继承函数里,函数外面根本拿不到里面的这个空函数,安全可靠。

三、Object.setPrototypeOf

Object.setPrototypeOf(child.prototype,parent.prototype);

该方法是ES6新增的设置原型的方法,它可以直接关联两个对象,而不需要重新将child的constructor手动拉回,简单方便,实在是原型继承,必备良药。

四、Object.create

child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;

 此种方法也是安全可靠,使用方便无隐患,缺点也是需要手动设置一下自己的constructor.

posted @ 2019-09-17 16:11  liujiekun  阅读(508)  评论(0编辑  收藏  举报