我试图在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模块


https://github.com/pinojs/pino/blob/master/pino.js


谢谢,

最佳答案

原因是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

09-11 17:45