JavaScript: Детерминированность
У функций в любом языке программирования есть фундаментальные свойства. Они помогают понимать, как функция будет вести себя в разных ситуациях, как её тестировать и где применять. Одно из таких свойств — детерминированность.
Детерминированная функция всегда возвращает один и тот же результат при одинаковых входных данных. Например, детерминированной можно назвать функцию, которая считает количество символов:
import { length } from 'hexlet-basics/string';
length('hexlet'); // 6
length('hexlet'); // 6
length('wow'); // 3
length('wow'); // 3Сколько бы раз мы ни вызывали эту функцию с аргументом 'hexlet', она всегда вернёт 6.
Недетерминированные функции
К противоположному типу относятся недетерминированные функции. Они могут возвращать разные результаты при одинаковых входных данных или при их отсутствии (функции без параметров). Хороший пример — функция, возвращающая случайное число:
Math.random(); // 0.09856613113197676
Math.random(); // 0.8839904367241888У этой функции нет аргументов, но результат каждый раз разный. Если хотя бы один вызов из миллиона даст другой результат, функция считается недетерминированной.
Детерминированная: Недетерминированная:
length('abc') → всегда 3 Math.random() → 0.42
length('abc') → всегда 3 Math.random() → 0.91
length('abc') → всегда 3 Math.random() → 0.07Почему это важно
Детерминированность влияет на то, как мы работаем с функциями:
- детерминированные функции легко тестировать и предсказывать;
- их проще оптимизировать и использовать повторно;
- недетерминированные функции сложнее проверять, потому что результат меняется.
Поэтому там, где это возможно, лучше стремиться к тому, чтобы функция была детерминированной.
Задание
Сгенерируйте случайное целое число от 0 до 10 (включительно) и выведите его на экран.
Используйте Math.random() (возвращает число от 0 до 1) и Math.round() (округляет до целого).
Полезное
Ваше упражнение проверяется по этим тестам
// @ts-check
import { expect, test, vi } from 'vitest';
test('deterministic', async () => {
const consoleLogSpy = vi.spyOn(console, 'log');
await import('./index.js');
const firstArg = consoleLogSpy.mock.calls.join('\n');
expect(firstArg).not.toEqual('');
const value = Number(firstArg);
expect(Number.isInteger(value)).toEqual(true);
expect(value).toBeGreaterThanOrEqual(0);
expect(value).toBeLessThanOrEqual(10);
});Решение учителя откроется через:
20:00
