javascript中的3种继承实现方法
使用Object.create实现类式继承
下面是官网的一个例子
//Shape-superclass functionShape(){ this.x=0; this.y=0; } Shape.prototype.move=function(x,y){ this.x+=x; this.y+=y; console.info("Shapemoved."); }; //Rectangle-subclass functionRectangle(){ Shape.call(this);//callsuperconstructor. } Rectangle.prototype=Object.create(Shape.prototype); varrect=newRectangle(); rectinstanceofRectangle//true. rectinstanceofShape//true. rect.move(1,1);//Outputs,"Shapemoved."
此时Rectangle原型的constructor指向父类,如需要使用自身的构造,手动指定即可,如下
Rectangle.prototype.constructor=Rectangle;
使用utilities工具包自带的util.inherites
语法
util.inherits(constructor,superConstructor)
例子
constutil=require('util'); constEventEmitter=require('events'); functionMyStream(){ EventEmitter.call(this); } util.inherits(MyStream,EventEmitter); MyStream.prototype.write=function(data){ this.emit('data',data); } varstream=newMyStream(); console.log(streaminstanceofEventEmitter);//true console.log(MyStream.super_===EventEmitter);//true stream.on('data',(data)=>{ console.log(`Receiveddata:"${data}"`); }) stream.write('Itworks!');//Receiveddata:"Itworks!"
也很简单的例子,其实源码用了ES6的新特性,我们瞅一瞅
exports.inherits=function(ctor,superCtor){ if(ctor===undefined||ctor===null) thrownewTypeError('Theconstructorto"inherits"mustnotbe'+ 'nullorundefined'); if(superCtor===undefined||superCtor===null) thrownewTypeError('Thesuperconstructorto"inherits"mustnot'+ 'benullorundefined'); if(superCtor.prototype===undefined) thrownewTypeError('Thesuperconstructorto"inherits"must'+ 'haveaprototype'); ctor.super_=superCtor; Object.setPrototypeOf(ctor.prototype,superCtor.prototype); };
其中Object.setPrototypeOf即为ES6新特性,将一个指定的对象的原型设置为另一个对象或者null
语法
Object.setPrototypeOf(obj,prototype)
obj为将要被设置原型的一个对象
prototype为obj新的原型(可以是一个对象或者null).
如果设置成null,即为如下示例
Object.setPrototypeOf({},null);
感觉setPrototypeOf真是人如其名啊,专门搞prototype来玩。
那么这个玩意又是如何实现的呢?此时需要借助宗师__proto__
Object.setPrototypeOf=Object.setPrototypeOf||function(obj,proto){ obj.__proto__=proto; returnobj; }
即把proto赋给obj.__proto__就好了。
使用extends关键字
熟悉java的同学应该非常熟悉这个关键字,java中的继承都是靠它实现的。
ES6新加入的class关键字是语法糖,本质还是函数.
在下面的例子,定义了一个名为Polygon的类,然后定义了一个继承于Polygon的类Square。注意到在构造器使用的super(),supper()只能在构造器中使用,super函数一定要在this可以使用之前调用。
classPolygon{ constructor(height,width){ this.name='Polygon'; this.height=height; this.width=width; } } classSquareextendsPolygon{ constructor(length){ super(length,length); this.name='Square'; } }
使用关键字后就不用婆婆妈妈各种设置原型了,关键字已经封装好了,很快捷方便。