TypeScript - лучший способ восстановить цепочку прототипов? (Node.js) - PullRequest
0 голосов
/ 14 июля 2020

У меня есть вопросы по функции Object.setPrototypeOf(this, new.target.prototype) из-за этого предупреждения MDN:

Предупреждение: изменение [[Prototype]] объекта является современным JavaScript движки оптимизируют доступ к свойствам, что в настоящее время очень медленно работает в каждом браузере и движке JavaScript. Кроме того, последствия изменения наследования незаметны и обширны и не ограничиваются просто временем, проведенным в операторе Object.setPrototypeOf (...), но могут распространяться на любой код, имеющий доступ к любому объекту, чей [ [Prototype]] был изменен.

Поскольку эта функция является частью языка, разработчикам движков по-прежнему приходится выполнять эту функцию эффективно (в идеале). Пока разработчики движка не решат эту проблему, если вы беспокоитесь о производительности, вам следует избегать установки [[Prototype]] объекта. Вместо этого создайте новый объект с желаемым [[Prototype]] с помощью Object.create ().

Итак, как лучше всего восстановить строку прототипа в TypeScript (Node.js) без используя Object.setPrototypeOf(this, new.target.prototype) (но используя классы)? Это все из-за промежуточного программного обеспечения управления ошибками, реализованного в Express, в котором мне нужно использовать instanceof, чтобы определить источник ошибки и, таким образом, вернуть правильный ответ, но всякий раз, когда я создаю класс, который расширяется от Error , error instanceof Error возвращает true, а error instanceof CustomError возвращает false. Проведя небольшое исследование, я нашел это в официальной документации TypeScript:

Мета-свойство new.target - это новый синтаксис, представленный в ES2015. Когда экземпляр конструктора создается с помощью new, значение new.target устанавливается как ссылка на функцию конструктора, изначально использовавшуюся для выделения экземпляра. Если функция вызывается, а не создается через new, для new.target устанавливается значение undefined.

new.target пригодится, когда требуется Object.setPrototypeOf или proto для установки в конструкторе класса. Один из таких вариантов использования наследуется от Error в NodeJS v4 и выше

// Example

class CustomError extends Error {
    constructor(message?: string) {
        super(message); // 'Error' breaks prototype chain here
        Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
    }
}
// Results

var CustomError = (function (_super) {
  __extends(CustomError, _super);
  function CustomError() {
    var _newTarget = this.constructor;
    var _this = _super.apply(this, arguments);  // 'Error' breaks prototype chain here
    _this.__proto__ = _newTarget.prototype; // restore prototype chain
    return _this;
  }
  return CustomError;
})(Error);

И я подумал, что все идеально, так как код в момент преобразования, я полагаю, что компилятор позаботится об этой медленной функции и заменит ее другой более эффективной процедурой, но, к моему удивлению, это не так, и я немного беспокоюсь о производительности (я работаю над большим проектом ).

Я использую TypeScript версии 3.9.6 в Node 14.5.0, это скриншоты выполненных мною тестов:

TypeScript с Node

TypeScript Playground

Результаты компилятора TypeScript

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...