js中的幾種繼承實現

使用Object.create實現類式繼承

下面是官網的一個例子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爲將要被設置原型的一個對象
prototypeobj新的原型(能夠是一個對象或者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';
  }
}

使用關鍵字後就不用婆婆媽媽各類設置原型了,關鍵字已經封裝好了,很快捷方便。

相關文章
相關標籤/搜索