Я пытаюсь расширить класс в 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
Спасибо,
Причина в том, что определение Pino
(pino
в модуле) возвращает не экземпляр pino
а синтезированный объект - в конце он имеет оператор return instance
.
Хотя этот возвращенный объект получил конкретный прототип, он не является pino.prototype
.
Поэтому, когда создается экземпляр Logger
, он также возвращает этот "чужой" объект, в то время как rrr
остается " Logger.prototype
" в неиспользованном 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
pino.prototype
(который помог бы с instanceof pino
), это не позволило бы расширить «класс».
Примечание: я поддерживаю Пино.
Функция, возвращаемая функцией require('pino')
является фабричной функцией, а не функцией конструктора. Таким образом, синтаксис class
сахар не будет работать для настройки прототипа Pino: мы не раскрываем прототип.
Чтобы настроить Pino, нужно обернуть экземпляр своей функциональностью:
const instance = require('pino')()
Object.defineProperties(instance, {
rrr: {
value: function () {
this.info('this is the rrr function')
}
}
})
instance.rrr()
Я настоятельно рекомендую узнать, как объекты в Javascript действительно работают, вместо того, чтобы полагаться на (на мой взгляд, катастрофический) синтаксис class
. Два Столпа Javascript - превосходный набор статей на эту тему. И вы не знаете, JS: this
и объектные прототипы - это большая углубленная книга на эту тему.
Pino
. Может быть, он возвращает простой объект, а не правильный экземпляр? Вы можете проверить, есть лиpp instanceof Logger
(возможно,false
) и есть лиpp instanceof Pino
.