咱们学JAVA的时候说到继承就是一个extends ClassName的事情,可是在JS的世界里继承和咱们在JAVA所认识的继承实现方法又有一些不一样,大家真的了解JS的继承吗?就当大家很了解了,毕竟是基础知识,我就简单说说app
简言之就是把被继承的对象赋值给继承者的原型对象函数
function Super() { this.name = 'mirok'; } Super.prototype.showName = function () { console.log(this.name); } function Sub() { this.name = 'july'; } Sub.prototype = new Super(); const obj = new Sub(); obj.showName(); //输出july
原型实现继承虽然能够,可是也有相应的弊端,例如new Super()构建多个实例,继承里面的方法被其中一个实例重写,就会影响其余实例,也就是说原型里的是全部实例所共享的,这是咱们不肯看到的,所以就有如下的方法。this
简言之就是在继承者的构造函数中去调用被继承者的构造函数(即便用apply()/call()实现)prototype
function Super() { this.supername = 'mirok'; } function Sub() { Super.call(this) this.name = 'july'; } Sub.prototype = new Super(); const obj = new Sub(); obj.name; //july obj.supername; //mirok
这种方式实现的继承相对于以前的来讲不只解决了以前的问题还能向被继承者传参数,可是也有必定的弊端,即容易覆盖自己的属性,解决方法就是在调用被继承者的构造函数再对本身添加属性,也就是说上面的Super.call要在this.name定义属性以前。另外一个弊端就是继承的是没法共享的code
这个就是组合前面的原型链继承和借用构造函数继承二者之长,也就是说既能在继承后的实例都有一份属性又能共用对象
function Super() { this.name = 'mirok'; } Super.prototype.showName = function () { console.log(this.name); } function Sub1() { Super.call(this); this.name = 'july'; } function Sub2() { Super.call(this); this.name = 'deny'; } Sub1.prototype = new Super(); Sub2.prototype = new Super(); const obj1 = new Sub1(); const obj2 = new Sub2(); obj1.showName(); // july obj2.showName(); // deny
这个比较特殊一点,就是在一个函数里去作原型链继承的事情继承
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); }
ES5规范了这类写法,就是Object.create(),可是弊端和第一种相似,由于不是咱们理想的继承这里就不详细介绍原型链
这个也比较特殊,就是把继承的事情放在一个函数里去作,再把对象返回原型
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); } function factory() { const person = {name:'mirok', age: 22}; const obj = object(person); obj.show = function() {console.log(this.name)} return obj; } factory().show(); //'mirok'
至于弊端可见而知,不能实现共享io
组合继承有个弊端就是会调用两次被继承者的构造函数,解决方法就是使用寄生组合式继承。这又是什么呢?这个相对以前的比较复杂,可是高效的一点是只调用一次被继承者构造函数,原理就是经过寄生方式建立一个被继承者的副本,副本和被继承者共用一个prototype,这样就解决了以前的问题
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); } function factory(Sub, Super) { var proto = object(Super.prototype); //返回Super的一个副本 proto.constructer = Sub; //设置constructor指向, 由于新副本的原型对象被重写 Sub.prototype = proto; //副本做为sub的原型对象 } function Super () { this.name = 'july'; } Super.prototype.show = function () { console.log(this.name); } function Sub1 () { Super.call(this); this.name = 'mirok' } function Sub2 () { Super.call(this); this.name = 'deny' } factory(Sub1, Super); factory(Sub2, Super); var obj1 = new Sub1(); var obj2 = new Sub2(); obj1.show(); // mirok obj2.show(); // deny