JS: Прототипы

Теория: Полиморфизм подтипов

После перехода на AST у нас появилась хорошая база для следующего шага: полиморфизма.

До этого рендер часто выглядел как ветвление по типу тега: если тег одиночный, делаем одну строку, если парный - другую. Работает, но чем больше вариантов, тем больше условных конструкций.

Где появляется полиморфизм

Типичный фрагмент, который просится на переработку:

if (singleTagsList.has(tagName)) {
  return `<${tagName}>`;
}

return `<${tagName}>${content}</${tagName}>`;

Здесь явно видно два разных поведения.

  • SingleTag
  • PairedTag

Вместо одного большого if мы можем вынести поведение в сами объекты.

Динамическая диспетчеризация

Когда каждый тип знает, как рендерить себя, код упрощается:

  • вызываем toString()
  • конкретная реализация выбирается по фактическому типу объекта
const tag = new ...;
tag.toString();

Это и есть полиморфизм подтипов: общий интерфейс, разные реализации.

AST теперь хранит не просто данные

Вместо "обычных объектов" можно строить композицию инстансов:

const data = ['div', [
  ['hr'],
]];

const ast = parse(data);

ast instanceof PairedTag; // true
ast.children[0] instanceof SingleTag; // true

ast.toString(); // <div><hr></div>

Важный эффект: рекурсивный рендер становится естественным. Верхний узел рендерит себя и делегирует рендер детям.

Фабрика узлов

Чтобы не размазывать new SingleTag и new PairedTag по коду, удобно ввести фабрику:

buildNode(name, attributes, body, children);

Она решает, какой тип создать, а вызывающий код работает через общий контракт.

Что это дает на практике

Полиморфизм в этом уроке нужен не ради теории. Он решает конкретные проблемы:

  • уменьшается количество условной логики
  • проще добавлять новые типы узлов
  • поведение лежит рядом с данными
  • код лучше читается и легче расширяется

Итоги

Когда видите устойчивое ветвление "если тип A, делай X; если тип B, делай Y", это хороший кандидат на полиморфизм.

В нашем случае переход к SingleTag и PairedTag делает рендер HTML проще и подготавливает архитектуру к следующим изменениям.

Дальше

Завершено

0 / 10