Архитектура наследования через CryptoJS.lib.Base

В основе архитектуры библиотеки лежит минималистичная объектная система, реализованная через CryptoJS.lib.Base. Она задаёт единый способ создания «классов», расширения функциональности и построения иерархий без использования нативных классов ES6 (библиотека исторически ориентирована на более раннюю модель JavaScript).

Ключевая идея заключается в том, что каждый «класс» в системе CryptoJS — это функция-конструктор, расширяемая через метод extend, предоставляемый базовым объектом Base.

var MyClass = CryptoJS.lib.Base.extend({
    init: function (arg) {
        this.value = arg;
    }
});

Здесь extend создаёт новый конструктор, который наследует поведение базового объекта и добавляет или переопределяет методы.


Конструкция CryptoJS.lib.Base

CryptoJS.lib.Base выступает фундаментом всей объектной модели библиотеки. Он содержит минимальный набор механизмов:

  • создание экземпляров
  • расширение прототипов
  • примитивная инициализация объектов
  • поддержка «миксов» (mixins)

Упрощённо его можно представить как:

var Base = {
    extend: function (overrides) { ... },
    create: function () { ... },
    init: function () {}
};

Метод extend как ядро наследования

Главная логика наследования реализована в Base.extend. Он создаёт новый конструктор и связывает его с родительским объектом через прототип.

Механизм включает несколько шагов:

  1. Создание временной функции-конструктора
  2. Установка прототипа на родительский объект
  3. Копирование свойств из объекта расширения
  4. Определение конструктора нового класса

Упрощённая схема:

extend: function (overrides) {
    var Parent = this;

    var Child = function () {
        if (this.init) {
            this.init.apply(this, arguments);
        }
    };

    Child.prototype = Object.create(Parent.prototype);

    for (var key in overrides) {
        Child.prototype[key] = overrides[key];
    }

    Child.prototype.constructor = Child;

    Child.extend = Parent.extend;

    return Child;
}

Роль метода init

Вместо стандартного конструктора используется соглашение init. Это позволяет унифицировать поведение всех классов.

var WordArray = CryptoJS.lib.Base.extend({
    init: function (words, sigBytes) {
        this.words = words;
        this.sigBytes = sigBytes;
    }
});

При создании объекта через extend фактический вызов конструктора делегируется init, что обеспечивает единый стиль инициализации.


Создание экземпляров через create

Базовый класс также предоставляет метод create, который используется вместо new.

var instance = MyClass.create(arg);

Реализация обычно выглядит как обёртка над new:

create: function () {
    var instance = Object.create(this.prototype);
    this.apply(instance, arguments);
    return instance;
}

Это позволяет скрыть детали конструктора и унифицировать создание объектов во всей библиотеке.


Цепочка прототипов и делегирование

Каждый новый «класс» в CryptoJS связан с родительским через прототипную цепочку. Это обеспечивает:

  • наследование методов без копирования
  • возможность переопределения поведения
  • доступ к базовым реализациям

При вызове метода движок JavaScript поднимается по цепочке:

Child.prototype → Parent.prototype → Base.prototype

Таким образом, если метод не найден в текущем объекте, он ищется выше по иерархии.


Переопределение методов

При расширении класса можно заменять существующие методы. Это основной механизм кастомизации.

var A = CryptoJS.lib.Base.extend({
    getValue: function () {
        return 1;
    }
});

var B = A.extend({
    getValue: function () {
        return 2;
    }
});

В B метод getValue перекрывает реализацию родителя.


Доступ к родительским методам

В классической реализации CryptoJS отсутствует нативный super, но доступ к родительской логике возможен через сохранение ссылки на прототип.

Часто используется паттерн сохранения базового метода:

var ParentMethod = this.someMethod;

this.someMethod = function () {
    ParentMethod.apply(this, arguments);
};

Либо через явное обращение к прототипу:

CryptoJS.lib.Base.prototype.method.call(this);

Миксины и композиция

Помимо наследования, Base поддерживает примитивную композицию поведения через копирование свойств.

При вызове extend любые дополнительные поля из объекта overrides просто копируются в прототип.

extend: function (overrides) {
    for (var key in overrides) {
        this.prototype[key] = overrides[key];
    }
}

Это делает возможным добавление функциональности без создания сложной иерархии.


Внутренняя модель объектов CryptoJS

Практически все структуры библиотеки строятся на Base:

  • CryptoJS.lib.WordArray
  • CryptoJS.lib.Cipher
  • CryptoJS.lib.Hasher
  • CryptoJS.lib.StreamCipher

Каждая из них расширяет базовый объект и добавляет специфичную криптографическую логику.

Например, Hasher добавляет:

  • обработку блоков данных
  • финализацию хеша
  • внутренние буферы состояния

Связь Base и криптографических примитивов

Архитектура Base используется не только как инструмент ООП, но и как механизм стандартизации поведения алгоритмов.

Все криптографические примитивы следуют одному контракту:

  • init — инициализация состояния
  • update — обработка данных
  • finalize — завершение вычисления

Этот контракт реализуется через наследование от базовых классов, где Base задаёт структуру расширения.


Особенности реализации extend в CryptoJS

Метод extend имеет несколько характерных особенностей, отличающих его от классических паттернов:

  1. Нет глубокого клонирования объектов — только поверхностное копирование
  2. Прототип создаётся через Object.create
  3. Конструктор заменяется на функцию-обёртку
  4. Наследование всегда одноуровневое, но может быть вложенным через цепочку extend

Инкапсуляция и соглашения

Вместо строгой инкапсуляции используется соглашение о приватности:

  • _property — внутренние поля
  • методы без подчёркивания — публичный API
var Example = CryptoJS.lib.Base.extend({
    _buffer: null,

    process: function () {
        this._buffer = [];
    }
});

Такой подход упрощает структуру, но оставляет внутреннюю логику доступной при необходимости.


Минимальная модель ООП как архитектурный выбор

CryptoJS.lib.Base реализует крайне лёгкую систему объектной ориентации:

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

Это сделано для обеспечения:

  • совместимости со старыми средами JavaScript
  • минимального overhead при выполнении
  • предсказуемости поведения в криптографических алгоритмах

Влияние Base на масштабируемость библиотеки

Благодаря унифицированной модели наследования:

  • добавление новых алгоритмов требует только расширения базовых классов
  • единый интерфейс упрощает интеграцию шифров и хеш-функций
  • поведение компонентов остаётся согласованным

Структура позволяет строить сложные цепочки обработки данных без изменения ядра библиотеки.


Ограничения архитектуры Base

Несмотря на гибкость, модель имеет ограничения:

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

Тем не менее, в контексте криптографических операций эти ограничения компенсируются простотой и предсказуемостью выполнения.