Expression Language в Vega представляет собой компактный JavaScript-подобный синтаксис, встроенный в систему декларативных визуализаций. Он используется для вычисления значений сигналов, параметров, фильтров, вычисляемых полей и реактивных выражений внутри графиков.
Главная особенность — выполнение выражений происходит не в глобальном
JavaScript-контексте, а в изолированной среде интерпретатора, где
доступны только ограниченные переменные и функции: datum,
event, signals, а также набор математических и
логических операций.
Такое ограничение обеспечивает безопасность и переносимость спецификаций, но усложняет отладку.
Каждое выражение в Vega компилируется в функцию интерпретатора и исполняется в момент:
В отличие от обычного JavaScript, выражения не имеют доступа к внешним переменным и работают в строго определённой области видимости.
Ключевые источники данных внутри выражений:
Пример выражения:
"expr": "datum.value > 10 ? 'high' : 'low'"
Большинство проблем в Expression Language связано не с синтаксисом JavaScript как таковым, а с ограничениями окружения выполнения.
Типичная ошибка:
Cannot read property 'x' of undefined
Возникает, когда datum отсутствует или структура данных
не соответствует ожидаемой.
Проблемные выражения:
datum.a.b
если datum.a равен null.
Корректный подход:
datum.a && datum.a.b
или
datum.a ? datum.a.b : 0
Сигналы могут быть не определены в момент первого вычисления.
signal("brush").extent[0]
Ошибка возникает, если brush ещё не создан или не
инициализирован.
Более устойчивый вариант:
signal("brush") ? signal("brush").extent[0] : 0
Expression Language не выполняет строгую типизацию. Это приводит к скрытым проблемам:
NaN после арифметических операцийПример:
datum.value + 10
Если datum.value — строка, результат будет
строковым.
Защита:
+datum.value + 10
Основной инструмент диагностики выражений — Vega Editor. Он предоставляет:
Ошибки выражений отображаются в консоли и overlay-панели.
Сигналы могут использоваться как промежуточные точки отладки.
{
"name": "debug_value",
"update": "datum.value"
}
Далее значение можно наблюдать через инспектор сигналов.
В Expression Language доступна ограниченная функция логирования:
log(datum.value)
Однако использование log зависит от конфигурации
интерпретатора Vega и может быть отключено в production-сборках.
Один из эффективных методов — последовательное упрощение выражения.
Исходное выражение:
datum.a > 10 && signal("enabled") ? datum.b * 2 : datum.c / datum.d
Шаги упрощения:
datum.a
signal("enabled")
datum.b * 2
datum.c / datum.d
Такой подход позволяет локализовать источник ошибки.
Vega-Lite использует Expression Language в ограниченном контексте, особенно в трансформациях:
calculatefilterwindow (частично)Пример calculate:
{
"calculate": "datum.sales * 1.2",
"as": "adjusted_sales"
}
datum.sales * 1.2
если sales не существует
"100" * 1.2
datum.value > threshold
если threshold не определён как сигнал или поле
Expression Language в Vega интерпретируется, а не компилируется в нативный JavaScript код.
Это означает:
При ошибке интерпретатор возвращает:
undefined как fallback;datum является ключевой переменной, но его содержимое
зависит от контекста:
Ошибка:
datum.value
в сигнале приведёт к datum is undefined.
Корректное разделение контекстов:
datumsignal("name")eventСобытия мыши и клавиатуры передаются через event.
Пример:
"on": {
"click": "event.x"
}
Типичные проблемы:
event.x и
event.clientXДля диагностики полезно временно возвращать объект:
event
datum.a.b.c.d
Любой null в цепочке приводит к падению выражения.
Устойчивый вариант:
datum.a && datum.a.b && datum.a.b.c && datum.a.b.c.d
datum.a / datum.b
если datum.b = 0, результатом будет
Infinity.
datum.value + signal("offset")
если offset не число, возникает неявное преобразование
типов.
Number(datum.value)
или
+datum.value
datum.value ? datum.value : 0
или
datum.value || 0
(с осторожностью, так как 0 также считается falsy)
signal("x") != null ? signal("x") : 0
Сигналы в Vega образуют граф зависимостей. Ошибка в одном сигнале может каскадно влиять на десятки выражений.
Для диагностики полезно:
Пример цепочки:
"a" -> "b" -> "c"
Ошибка в a делает некорректными b и
c.
Ошибки делятся на два класса:
Пример:
datum.value >
В крупных спецификациях Vega выражения часто распределены по:
Отладка упрощается при временном разбиении:
Сигналы могут выступать как промежуточные переменные:
{
"name": "step_debug",
"update": "datum.value * 2"
}
или цепочка:
{
"name": "step1",
"update": "datum.value"
},
{
"name": "step2",
"update": "signal('step1') * 2"
}
Такой подход позволяет локализовать момент появления ошибки.
При ошибке Expression Language Vega часто:
null в вычисление;Это создаёт эффект «тихих ошибок», когда график отображается частично некорректно без явного падения.