扩展类方法不公开

时间:2019-01-12 10:58:50

标签: javascript node.js class ecmascript-6

我正在尝试使用javascript扩展一个类,并向该类添加一些额外的功能。

const Pino = require('pino');

class Logger extends Pino {
  constructor(options = { name: 'isWorking' }) {
    super(options);
    this.check = "1234";
    this.ppp = () => {}
  }

  rrr() {}
}

let pp = new Logger();
console.log(pp.check)
console.log(pp.ppp)
console.log(pp.rrr)
console.log(pp instanceof Logger)
console.log(pp instanceof Pino)

这是输出

1234
[Function]
undefined
false
false

为什么rrr函数没有公开?我想到了重写基类。这应该适用于普通班级,这个Pino班级有什么特别之处?

注意:此处pino基类是javascript模块

谢谢

2 个答案:

答案 0 :(得分:2)

注意:我是Pino的维护者。

require('pino')返回的函数是http://review.romancecapsule.com,而不是“构造函数”函数。因此,class sugar语法不适用于自定义Pino原型:我们不会公开该原型。

要自定义Pino,可以使用自己的功能包装实例:

const instance = require('pino')()
Object.defineProperties(instance, {
  rrr: {
    value: function () {
      this.info('this is the rrr function')
    }
  }
})

instance.rrr()

我强烈建议您了解Javascript对象真正起作用的方式,而不要依赖(我认为是灾难性的)class语法。 factory function是关于该主题的出色文章集。 The Two Pillars of Javascript是一本关于该主题的深入书籍。

答案 1 :(得分:1)

原因是Pino(模块中的pino)的定义不返回pino的实例,而是返回一个合成对象-它具有一个return instance最后声明。

尽管返回的对象已收到特定的原型,但不是pino.prototype

因此,在创建Logger的实例时,它也会返回此“外来”对象,而rrr在未使用的Logger.prototype上保持“孤立”状态。

请参阅以下简化演示:

function Pino() { return new Date(); }

class Logger extends Pino {
    rrr() { return 1; }
}

const a = new Pino;
const b = new Logger;

console.log(a instanceof Pino); // false
console.log(b instanceof Logger); // false
console.log(b instanceof Pino); // false
console.log(b instanceof Date); // true

console.log(typeof b.rrr); // undefined

如果pino仅返回适当的实例(this),则rrr可用:

function Pino() {  } // returns `this`

class Logger extends Pino {
    rrr() { return 1; }
}

const a = new Pino;
const b = new Logger;

console.log(a instanceof Pino); // true
console.log(b instanceof Logger); // true
console.log(b instanceof Pino); // true
console.log(b instanceof Date); // false (obviously)

console.log(typeof b.rrr); // function

难以解决

如果您确实需要扩展,则可以这样进行,但是最好让库作者使它们的类可扩展:

function Pino() { return new Date(); }

function PinoClass() {} // Don't define anything in this class
PinoClass.prototype = Object.getPrototypeOf(new Pino);

class Logger extends PinoClass {
    rrr() { return 1; }
}

const a = new Pino;
const b = new Logger;

console.log(a instanceof Pino); // false
console.log(b instanceof Logger); // true
console.log(b instanceof Pino); // false
console.log(b instanceof Date); // true

console.log(typeof b.rrr); // function