SWC (Speedy Web Compiler) реализует собственный высокопроизводительный трансформатор JavaScript/TypeScript кода, в котором поддержка классов и наследования занимает ключевое место. При обработке современных синтаксических конструкций SWC преобразует их в совместимый ES5/ES2015 код, сохраняя семантику спецификации ECMAScript и оптимизируя результирующий вывод для выполнения в широком спектре окружений.
Конструкция class в современном JavaScript является
синтаксическим сахаром над прототипным наследованием. SWC выполняет
декомпозицию классов в набор функций, присваиваний свойств прототипу и
вспомогательных операций, обеспечивающих корректную инициализацию
экземпляров.
Базовый класс:
class A {
constructor(x) {
this.x = x;
}
method() {
return this.x;
}
}
После трансформации SWC (упрощённая форма):
function A(x) {
this.x = x;
}
A.prototype.method = function () {
return this.x;
};
Ключевая цель трансформации — сохранить поведение this,
прототипные цепочки и контекст вызова методов.
Метод constructor всегда преобразуется в обычную
функцию-конструктор. Все поля, объявленные внутри конструктора, остаются
частью инициализации экземпляра.
Особенность SWC заключается в строгом сохранении порядка выполнения инструкций внутри конструктора, поскольку он может содержать:
super()
Пример:
class A {
constructor() {
this.a = 1;
this.b = 2;
}
}
Результат:
function A() {
this.a = 1;
this.b = 2;
}
Методы класса переносятся в prototype. SWC не использует
Object.defineProperty по умолчанию, если не активированы
дополнительные опции, такие как сохранение дескрипторов.
class A {
method() {
return 42;
}
}
Трансформация:
A.prototype.method = function () {
return 42;
};
При этом сохраняется важное свойство: методы не перечисляемы в циклах
for…in, если используется корректная конфигурация
трансформации с дескрипторами.
Статические члены класса переносятся непосредственно на функцию-конструктор.
class A {
static foo() {
return 10;
}
}
Результат:
A.foo = function () {
return 10;
};
Статические свойства также могут трансформироваться в присваивания:
class A {
static version = 1;
}
При включённой поддержке полей класса:
A.version = 1;
Наиболее сложный аспект трансформации — поддержка наследования через
extends. SWC должен корректно построить цепочку прототипов
и обеспечить доступ к super.
class A {
constructor(x) {
this.x = x;
}
}
class B extends A {
constructor(x, y) {
super(x);
this.y = y;
}
}
Трансформация включает несколько ключевых шагов:
B
A.call
Упрощённый результат:
function B(x, y) {
A.call(this, x);
this.y = y;
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
Особое внимание SWC уделяет корректной обработке
super.method() и super().
class A {
constructor(x) {
this.x = x;
}
}
class B extends A {
constructor(x) {
super(x);
this.y = 10;
}
}
Трансформация требует сохранения правильного контекста:
function B(x) {
A.call(this, x);
this.y = 10;
}
SWC гарантирует, что super() вызывается до обращения к
this, что соответствует спецификации.
При переопределении методов SWC просто заменяет функцию на прототипе дочернего класса.
class A {
method() {
return 1;
}
}
class B extends A {
method() {
return 2;
}
}
Результат:
function A() {}
A.prototype.method = function () {
return 1;
};
function B() {
A.apply(this, arguments);
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
B.prototype.method = function () {
return 2;
};
Когда метод дочернего класса вызывает super.method(), SWC
создаёт внутреннюю ссылку на прототип родителя.
class A {
method() {
return 1;
}
}
class B extends A {
method() {
return super.method() + 1;
}
}
Трансформация требует создания вспомогательных функций (упрощённо):
B.prototype.method = function () {
return A.prototype.method.call(this) + 1;
};
Фактически SWC использует более сложную обвязку для корректного поиска метода в цепочке прототипов, особенно при динамическом наследовании.
Статические методы также наследуются через прототип функции-конструктора.
class A {
static foo() {
return 1;
}
}
class B extends A {}
После трансформации:
function A() {}
A.foo = function () {
return 1;
};
function B() {}
B.__proto__ = A;
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
Таким образом, B.foo доступен через цепочку
[[Prototype]] функции.
Поля экземпляра могут объявляться вне конструктора:
class A {
x = 1;
}
class B extends A {
y = 2;
}
SWC преобразует это в инициализацию внутри конструктора:
function A() {
this.x = 1;
}
function B() {
A.call(this);
this.y = 2;
}
Порядок инициализации строго сохраняется:
SWC поддерживает приватные поля через WeakMap или
замыкания, в зависимости от конфигурации трансформации.
class A {
getX() {
return this.#x;
}
}
Трансформация:
var _x = new WeakMap();
function A() {
_x.set(this, 10);
}
A.prototype.getX = function () {
return _x.get(this);
};
Этот подход обеспечивает инкапсуляцию и предотвращает доступ извне класса.
SWC сохраняет поведение оператора instanceof, поскольку
прототипная цепочка строится через Object.create.
B.prototype = Object.create(A.prototype);
Это гарантирует:
new B() instanceof B === true
new B() instanceof A === true
SWC применяет ряд оптимизаций:
Object.defineProperty при упрощённой
конфигурации
Также SWC может различать режимы трансформации:
В loose режиме:
super
class A {
method() {}
}
Loose:
A.prototype.method = function () {};
Spec:
Object.defineProperty(A.prototype, "method", {
value: function () {},
enumerable: false,
writable: true,
configurable: true,
});
Выбор режима влияет на производительность и точность соответствия стандарту.
SWC корректно обрабатывает классы, вложенные в функции, включая доступ к внешним переменным:
function createClass(x) {
return class {
getX() {
return x;
}
};
}
Трансформация сохраняет замыкание:
function createClass(x) {
return function () {
this.getX = function () {
return x;
};
};
}
(в реальной реализации структура может быть более оптимизирована через прототип).
Внутренняя модель SWC для классов и наследования сводится к трём базовым механизмам:
super, private и
static
Эти механизмы позволяют полностью эмулировать поведение ECMAScript классов в средах, где они не поддерживаются нативно, сохраняя корректность наследования, инкапсуляции и полиморфизма.