js的继承机制
js的继承简单点来讲就是把变量想办法挂到要继承该函数的函数上面,靠语言来描述似乎很是苍白。那么首先我们先来讲一下原生继承的几种方法:
1.构造继承
function Parent(){
this.name=name;
this.age=age;
}
Parent.prototype.test=function(){
console.log(this.name)
}
function Parent1(type,sex){
Parent.call(this,'小明',18);//利用call方法传入this,执行父构造函数
this.type=type;
this.sex=sex;
}
在浏览器里面跑一下结果可得:
大家可以看到,虽然构造函数被成功的继承了,但是原型里面的函数没有被成功继承,这也是构造继承的一个缺点。
2.原型继承
原型继承实际上就是把父类的实例作为子类的原型,也可以理解父类的实例属性成为了子类的原型属性,例子:
function Parent(name,age){
this.name=name;
this.age=age;
}
Parent.prototype.test=function(){
console.log(this.name)
}
function Parnet1(type,sex){
this.type=type;
this.sex=sex;
}
Parentt1.prototype=new Parent("小芳",12)
Parnet1.prototype.constructor=Parent1
原型继承有两个缺点:
1.重写子类的原型 等于 父类的一个实例,(父类的实例属相变成子类的原型属性)如果父类包含引用类型的属性,那么子类所有实例都会共享该属性(包含引用类型的原型属性会被实例共享),一旦该引用类型的实例被修改,那所有的都会被修改,这就非常的不友好了,大家可以仔细体会一下。
2.在创建子类实例时,不能向父类的构造函数传递参数,只能在第一次构造实例传值的时候给值
小插曲:曾经有个刚入行的同学跟我说,为什么不直接用Parnet1.prototype=Parent.prototype,那多简单。我想说你敢这么用,那不就是坑吗,因为这里的原型实际上是一个对象,对象属于引用类型,当你对Parent1.prototype增加原型方法的时候,就会导致Parentt.prototype上也会多出这个方法,如果子类的这个方法特比尔重要,你又随便给别人了,那不就乱套了吗!!!
3 组合继承
既然原型继承和构造继承都有缺点,那我们领个都结合起来,那不就完美了吗,我这边给大家一个最好用最简单的一种组合继承方式:
function Parent(name,age){
this.name=name;
this.age=age;
}
Parent.prototype.test=function(){
console.log(this.name)
}
function Parent1(type,sex){
Parent.call(this,"小花",18)
this.type=type;
this.sex=sex;
}
Parent1.prototype=Object.create(Parent.prototype)
Parent1.prototype.constructor=Parent1;
Parent1.prototype.test1=function(){
console.log(this.age)
}
下面测试一下:
大家可以看到效果非常好,原型方法全部挂到子类上了,实例也全部构造成功。推荐大家以后用这种方法,简单,方便。
扩展
关于es6的class继承,这篇文章就不在写了。今天我们会稍微介绍一下es6的Object.create()的用法,先看个例子:
哎,不知道有没有同学会不会有疑惑,使用Object.create()之后,括号里面的东西竟然跑到了我们赋值对象的原型上,对,你没有看错,这正是Object.create()的一种用法,下面再看一种情况:
当Object.create()只有一个参数,会默认挂到一个空对象上,但是当我们想直接赋值的时候,一定要按照上面的方法赋值。Object.create的其他用法这边就不太详述,后面会专门写一篇文章来介绍它。今天在这里我们只要知道一点,
func.protoype=O bject.create(ParFunc.prototype)的作用是将ParFunc.prototype给到func.prototype.proto上面,而不是func.prototype上,这点大家一定要理解,这点是我们使用它来解决继承问题的关键。下面再给一个相关例子:
//手写一个bind函数
Function.prototype.mybind=function(thisArg, ...arg){
var that=this;
var newFunc=function(...arr){
var _that=this instanceof that ? this:thisArg ;
that.apply(_that,arg.concat(arr))
}
newFunc.prototype=Object.create(this.prototype);//体会一下这里面的用法
newFunc.prototype.constructor=newFunc
return newFunc
}