JavaScript
Область кода Выражения должна содержать код JavaScript.
Код Выражения является телом функции, которая должна возвращать значение. Для возврата этого значения используется return
. Однако, если код представлен единственным выражением JavaScript, то применять return
не обязательно.
Примечание. Имена узлов/переменных/выражений чувствительны к регистру.
Дерево данных доступно в коде JavaScript как объект глобальной области видимости с именем ${Имя_корневого_узла}
. Объект дерева данных объединяет исходное дерево и узлы, формируемые по Выражениям. В Выражении возможно использование ссылок на другие выражения.
При ссылках на узлы дерева имеется возможность задавать абсолютные или относительные пути. Абсолютные ссылки на узлы дерева представляют из себя строку, в которой через точку перечислены родители узла в их иерархии начиная с корневого узла. Пример: $Root.Orders.Order[0].Address
. Относительные ссылки могут задаваться с помощью встроенной функции Parent()
, возвращающей родителский узел для узла текущего Выражения. Пример: Parent().Order[0].Address
.
Узлы дерева, не являющиеся значениями простых типов, имеют свойство $Parent
, позволяющее обращаться к другим узлам из кода выражения относительно. У элементов массива свойство $Parent
возвращает объект типа Array.
У узлов-контейнеров, являющихся элементами массива, есть свойство $Index
, возвращающее индекс текущего элемента в массиве.
Следующий пример демонстрирует вычисление суммы значений узла в корне дерева и переменной:
// Вычисление суммы значений узла дерева и переменной
let result;
result = $Root.Value1 + this.Var.MyVar;
return result;
В теле скрипта можно использовать ссылки на другие узлы или переменные, в том числе новые, созданные в списке выражений. Через промежуточное выражение с типом Переменный можно передать массив. Ко входным Переменным можно обращаться через объект this.Var.
.
В данном примере для вычисления переменной result
используются ссылки на узел с именем $Root.Value1
и входную переменную MyVar
.
Для вывода результата в вычисляемое поле калькулятора используется команда return
, которая возвращает значение переменной result
, содержащей вычисленную сумму узлов дерева.
Компактный вариант кода вычисления суммы узлов дерева:
// Вычисление суммы значений узла и переменной
$Root.Value1 + this.Var.MyVar;
Пример создания и применения функции для вычисления сложного процента:
/*
Функция вычисления сложного процента
Z = I * (1 + R / 100%) (в степени T), где
Z — будущая сумма на счету;
I — начальная сумма вложений (InvestmentAmount);
R — процентная ставка в % (Rate);
T — срок вклада в годах (TimeSpan).
*/
function CompoundInterest(I, R, T) {
// Z - будущая сумма на счету;
let Z = I * Math.pow((1 + R / 100), T);
// накопленные проценты = Z - I
return Z - I;
}
// Вывод результата функции в качестве значения создаваемого в выражении узла
return CompoundInterest($Root.InvestmentAmount, $Root.Rate, $Root.TimeSpan);
В данном скрипте определена функция CompoundInterest(I, R, T)
, принимающая в качестве аргументов параметры расчета.
Для вывода результата скрипта в вычисляемое поле калькулятора используется команда return CompoundInterest($Root.InvestmentAmount, $Root.Rate, $Root.TimeSpan)
, где CompoundInterest
— объявленная функция, принимающая параметры из узлов дерева.
В коде JavaScript можно использовать встроенные функции Калькулятора:
function FinancialFormat(x) {
let s;
// s = x.concat(' руб.'); - используется метод JavaScript
s = Concat(x, ' руб.'); // - используется функция Калькулятора
return s;
}
return FinancialFormat($Root.SummaString);
Наименования встроенных функций Калькулятора и JavaScript не пересекаются. Функции Калькулятора всегда начинаются с большой буквы, однако, их можно переопределить в коде JS. Явного импорта функций Калькулятора (как это делается в компоненте JavaScript) делать не нужно.
Примечание: в отличии от компонента JavaScript в Калькуляторе не поддерживается объект Promise.
Импорт внешних модулей
Как и в компоненте JavaScript поддерживаются внешние модули, но в Калькуляторе (дерево) возможно использование только модульной системы CommonJS. Модульная система ES6 (ECMAScript 6) не поддерживается. С примерами и документацией использования модулей CommonJS можно ознакомиться в статье JavaScript: Импорт внешних модулей.
Особенности применения внешних модулей
Для импорта модуля CommonJS применяется функция require
. Пример:
const foo = require("foo/foo.js");
Выполнение модуля происходит при первом вызове require
. Последующие вызовы require
забирают выполненный модуль из кэша. Кэш функции require
доступен через объект require.cache
.
Важно: использование кэша для передачи значений между выражениями может привести к непредсказуемым результатам вычислений ввиду использования пула интерпретаторов.
Если при использовании модуля меняется его внутреннее состояние, и это влияет на будущий результат, то может потребоваться удалить его из кэша после использования в выражении с помощью объекта require.cache
:
let path = require.resolve("foo/foo.js");
delete require.cache[path]; // Очищается кэш модуля "foo/foo.js"
Важно: следует учитывать, что загрузка и выполнение модуля является затратной операцией, поэтому удаление модуля из кэша может серьёзно отразиться на производительности.
require
можно использовать для импорта файла json:
// загрузить json из файла в объект
let jsonAsObj = require('/path/to/file.json')
Панель быстрого доступа
На панели расположена кнопка вызова окна Предпросмотра и кнопки, по нажатию на которые в область кода выражения вставляется заготовка либо шаблон.
Предпросмотр — позволяет оценить корректность расчетов, отображая результирующее дерево. Горячая клавиша вызова — F3
.
Логические операции:
- && — Логическое "И";
- || — Логическое "ИЛИ";
- ! — Логическое "НЕ".
Операторы сравнения:
- = — Равно;
- != — Не равно;
- < — Меньше;
- > — Больше;
- <= — Меньше или равно;
- >= — Больше или равно.
Шаблоны:
- — для ввода вещественного числа, будет вставлено
0.0
. - — для ввода строки, будет вставлено
""
. - — для ввода даты, будет вставлена конструкция создания объекта, содержащего текущую дату. Пример:
new Date(2020, 1, 5)
. - — для ввода даты/времени, будет вставлена конструкция создания объекта, содержащего текущие дату/время. Пример:
new Date(2020, 1, 5, 13, 12, 50, 100)
.
Логические значения:
- false — Ложь;
- true — Истина.
Примеры
Имеется входное дерево данных:
Пример 1
В узле Root.Orders
создадим выражение OrdersCount
, подсчитывающее общее колличество элементов в массиве Root.Orders.Order
. Код JavaScript нового выражения будет следующим:
$Root.Orders.Order.length
Узел дерева Order
в контексте JavaScript является объектом типа Array и будет иметь свойство length
, которое используется для вывода длинны массива.
Абсолютной ссылкой на новый узел будет строка $Root.Orders.OrdersCount
. Относительно $Root.Orders.OrdersCount
функция Parent()
вернет узел Orders
, в котором содержится узел Order
. Поэтому для вычисления выражения так же будет работать код с относительной ссылкой на узел Order
:
Parent().Order.length
Пример 2
В узле Root.Orders
создадим выражение LastShipmentDate
, подсчитывающее максимальную дату ShippedDate
в массиве Root.Orders.Order
. Код JavaScript нового выражения будет следующим:
let orders = Parent().Order;
const c = orders.length;
if (!c) return undefined;
let lastDate = orders[0].ShipInfo.ShippedDate;
for (let i = 1; i < c; i++) {
let shippedDate = orders[i].ShipInfo.ShippedDate;
if (shippedDate > lastDate)
lastDate = shippedDate;
}
return lastDate;
Здесь переменной orders
присваивается массив Order
. Для перебора в цикле элементов массива используется конструкция orders[i]
, где i
— итерируемый в цикле индекс элемента массива.
Пример 3
Заменим строковые значения узлов $Root.Orders.Order[].ShipInfo.Freight
на вещественные. Эти узлы находятся в элементах массива Order
, поэтому для обращения к элементам используем функцию ItemIndex()
, возвращающую индекс текущего элемента в массиве:
Number($Root.Orders.Order[ItemIndex()].ShipInfo.Freight)
Для возвращения индекса элемента в массиве так же можно использовать свойство $Index
:
Number($Root.Orders.Order[Parent().$Parent.$Index].ShipInfo.Freight)
Здесь для обращения к элементам массива Order
используется относительная ссылка Parent().$Parent
. Функция Parent()
возвращает родителя узла Freight
, которым является узел ShipInfo
, а свойство $Parent
узла ShipInfo
возвращает элемент массива Order
, в котором содержится узел Freight
. Свойство $Index
элемента массива возвращает индекс этого элемента. Таким образом, конструкция Parent().$Parent.$Index
возвращает индекс элемента массива Order
, в котором содержится текущий узел Freight
. В процессе расчета Калькулятор (дерево) перебирает и пересчитывает все узлы дерева, для которых определены Выражения.
Для замены исходных значений узлов на новые, вычисленные в Выражении, необходимо включить опцию Заменять узел.