下面是官網的一個例子java
//Shape - superclass function Shape() { this.x = 0; this.y = 0; } Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); //call super constructor. } Rectangle.prototype = Object.create(Shape.prototype); var rect = new Rectangle(); rect instanceof Rectangle //true. rect instanceof Shape //true. rect.move(1, 1); //Outputs, "Shape moved."
此時Rectangle原型的constructor指向父類,如須要使用自身的構造,手動指定便可,以下函數
Rectangle.prototype.constructor = Rectangle;
utilities
工具包自帶的util.inherites
語法工具
util.inherits(constructor, superConstructor)
例子ui
const util = require('util'); const EventEmitter = require('events'); function MyStream() { EventEmitter.call(this); } util.inherits(MyStream, EventEmitter); MyStream.prototype.write = function(data) { this.emit('data', data); } var stream = new MyStream(); console.log(stream instanceof EventEmitter); // true console.log(MyStream.super_ === EventEmitter); // true stream.on('data', (data) => { console.log(`Received data: "${data}"`); }) stream.write('It works!'); // Received data: "It works!"
也很簡單的例子,其實源碼用了ES6
的新特性,咱們瞅一瞅this
exports.inherits = function(ctor, superCtor) { if (ctor === undefined || ctor === null) throw new TypeError('The constructor to "inherits" must not be ' + 'null or undefined'); if (superCtor === undefined || superCtor === null) throw new TypeError('The super constructor to "inherits" must not ' + 'be null or undefined'); if (superCtor.prototype === undefined) throw new TypeError('The super constructor to "inherits" must ' + 'have a prototype'); ctor.super_ = superCtor; Object.setPrototypeOf(ctor.prototype, superCtor.prototype); };
其中Object.setPrototypeOf
即爲ES6新特性,將一個指定的對象的原型設置爲另外一個對象或者nullprototype
語法code
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; return obj; }
即把proto
賦給obj.__proto__
就行了。
extends
關鍵字熟悉java
的同窗應該很是熟悉這個關鍵字,java中的繼承都是靠它實現的。
ES6新加入的class關鍵字是語法糖,本質仍是函數.
使用extends修改以前util.inherits
的例子,將會更簡單
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', function() { console.log('an event occurred!'); }); myEmitter.emit('event');
在下面的例子,定義了一個名爲Polygon的類,而後定義了一個繼承於Polygon的類 Square。注意到在構造器使用的 super(),supper()只能在構造器中使用,super函數必定要在this能夠使用以前調用。
class Polygon { constructor(height, width) { this.name = 'Polygon'; this.height = height; this.width = width; } } class Square extends Polygon { constructor(length) { super(length, length); this.name = 'Square'; } }
使用關鍵字後就不用婆婆媽媽各類設置原型了,關鍵字已經封裝好了,很快捷方便。