Node.js入门笔记(10):类继承

404 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

Node在源码中使用了大量的继承,在对源码的观察中我们来看一下实现继承的方式,官方推荐的node是使用extends来实现继承,但是从底层中依然是保留了原始的继承方法

1、源码实现

我们来看一下源码中的fs模块源码,fs模式是通过继承events模块实现的

function FSWatcher(){
    EventEmitter.call(this)
}
Uint8ClampedArray.inherits(FSWatcher,EventEmitter)

官方推荐我们使用util.inherits方法来实现继承,我们再源码中来看看对应的实现,这里我们抛开源码中的错误处理,来简单的看一下实现方法,其实是通过setPrototypeOf来实现的继承

    exports.inherits = function(ctor,superCtor){
        ctor.super = superCtor
        Object.setPrototypeOf(ctor.prorotype,superCtor.prorotype)
    }

2、setPrototypeOf

用法

让我们来看一下setProtype的用法

Object.setPrototypeOf(a.prototype,b.prototype)

这个api是对obj设置原型,prototype是给obj新设置的原型,返回值是指定的对象

来一个小栗子,我们声明一个Car的类,然后通过prototype设置某些函数在上面,但我们在声明另外一个类,并且实用继承的方式结合俩个类,那么我们在bike类中,就可以看出,我们同个new 一个bike,并且执行run函数的时候是可以自执行的,并且输出的值是我们定义在car类上面的函数值

function Car(){
    this.color = 'red'
    this.name = 'car'
} 
Car.prototype.run  = function(){
    console.log(this.name+' is run run run');
}
Car.prototype.getColor  = function(){
    console.log('color'+this.color);
}

function Bike(){
    this.color = 'blue'
    this.name = 'bike'
}
Bike.prototype.go = function (){
    console.log(this.name+' is go go go');
}

Object.setPrototypeOf(Bike.prototype,Car.prototype)
let b1= new Bike()

// let c1 = new Car()
b1.run()//bike is run run run

Object.setPrototypeOf()在 ECMAScript 2015 规范中。它通常被认为是设置对象原型的正确方法,而不是更具争议性的Object.prototype.__proto__属性 我们可以来看一下官方对整个api源码的解释,对于出传入的参数,我们会判断是否传入的数量大于俩个,否则会进行报错,并且我们需要typeof来进行判断传入的参数的类型

Object.appendChain = function(oChain, oProto) {
  if (arguments.length < 2) {
    throw new TypeError('Object.appendChain - Not enough arguments');
  }
  if (typeof oProto !== 'object' && typeof oProto !== 'string') {
    throw new TypeError('second argument to Object.appendChain must be an object or a string');
  }

  const oNewProto = oProto,
      oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain);

  for (const o1st = this.getPrototypeOf(o2nd);
    o1st !== Object.prototype && o1st !== Function.prototype;
    o1st = this.getPrototypeOf(o2nd)
  ) {
    o2nd = o1st;
  }

  if (oProto.constructor === String) {
    oNewProto = Function.prototype;
    oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
    this.setPrototypeOf(oReturn, oLast);
  }

  this.setPrototypeOf(o2nd, oNewProto);
  return oReturn;
}