Проверка входных параметров

Корректная инициализация и стабильная работа библиотеки Headroom.js напрямую зависят от валидности передаваемых параметров. Несмотря на то, что сама библиотека достаточно устойчива к ошибкам, отсутствие явной проверки может привести к непредсказуемому поведению: некорректному скрытию/появлению элемента, «дёрганию» интерфейса или полной неработоспособности.

Проверка входных данных позволяет:

  • гарантировать соответствие параметров ожидаемым типам;
  • предотвратить ошибки времени выполнения;
  • упростить отладку;
  • повысить надёжность пользовательского интерфейса.

Основные параметры Headroom.js

При создании экземпляра Headroom используются два ключевых аргумента:

const headroom = new Headroom(element, options);
  • element — DOM-элемент, к которому применяется поведение;
  • options — объект конфигурации.

Каждый из них требует отдельной проверки.


Проверка DOM-элемента

Тип и существование

Первое, что необходимо проверить — наличие и корректность элемента:

if (!element) {
  throw new Error("Headroom: элемент не передан");
}

if (!(element instanceof HTMLElement)) {
  throw new TypeError("Headroom: передан некорректный DOM-элемент");
}

Частые ошибки

  • Передача null или undefined
  • Передача строки вместо элемента ("#header" вместо document.querySelector)
  • Передача коллекции (NodeList, HTMLCollection)

Пример корректной инициализации

const element = document.querySelector("header");

if (!element) {
  console.warn("Header не найден");
} else {
  const headroom = new Headroom(element);
  headroom.init();
}

Проверка объекта options

Параметр options является необязательным, но при его наличии требуется убедиться, что это объект:

if (options && typeof options !== "object") {
  throw new TypeError("Headroom: options должен быть объектом");
}

Проверка отдельных свойств options

1. offset

Определяет, на каком расстоянии от верхней границы страницы начинается реакция.

if (options.offset !== undefined) {
  if (typeof options.offset !== "number" || options.offset < 0) {
    throw new TypeError("offset должен быть неотрицательным числом");
  }
}

Допускается также объект:

if (typeof options.offset === "object") {
  if (typeof options.offset.up !== "number" || typeof options.offset.down !== "number") {
    throw new TypeError("offset.up и offset.down должны быть числами");
  }
}

2. tolerance

Определяет чувствительность к прокрутке.

if (options.tolerance !== undefined) {
  const tol = options.tolerance;

  if (typeof tol === "number") {
    if (tol < 0) {
      throw new Error("tolerance не может быть отрицательным");
    }
  } else if (typeof tol === "object") {
    if (typeof tol.up !== "number" || typeof tol.down !== "number") {
      throw new TypeError("tolerance.up и tolerance.down должны быть числами");
    }
  } else {
    throw new TypeError("tolerance должен быть числом или объектом");
  }
}

3. classes

Позволяет переопределить CSS-классы.

if (options.classes !== undefined) {
  if (typeof options.classes !== "object") {
    throw new TypeError("classes должен быть объектом");
  }

  Object.values(options.classes).forEach(className => {
    if (typeof className !== "string") {
      throw new TypeError("имена классов должны быть строками");
    }
  });
}

4. scroller

Определяет контейнер прокрутки.

if (options.scroller !== undefined) {
  if (
    !(options.scroller instanceof HTMLElement) &&
    options.scroller !== window
  ) {
    throw new TypeError("scroller должен быть HTMLElement или window");
  }
}

5. callbacks

Headroom поддерживает ряд callback-функций:

  • onPin
  • onUnpin
  • onTop
  • onNotTop
  • onBottom
  • onNotBottom

Проверка:

const callbacks = [
  "onPin",
  "onUnpin",
  "onTop",
  "onNotTop",
  "onBottom",
  "onNotBottom"
];

callbacks.forEach(cb => {
  if (options[cb] !== undefined && typeof options[cb] !== "function") {
    throw new TypeError(`${cb} должен быть функцией`);
  }
});

Стратегии обработки ошибок

1. Жёсткая остановка (throw)

Подходит для разработки:

throw new Error("Некорректный параметр");

2. Мягкая обработка (console.warn)

Подходит для production:

console.warn("Некорректный параметр, используется значение по умолчанию");

3. Значения по умолчанию

const defaultOptions = {
  offset: 0,
  tolerance: 0
};

options = { ...defaultOptions, ...options };

Централизованная функция валидации

Создание отдельной функции упрощает повторное использование:

function validateHeadroomOptions(element, options = {}) {
  if (!(element instanceof HTMLElement)) {
    throw new Error("Некорректный элемент");
  }

  if (typeof options !== "object") {
    throw new Error("options должен быть объектом");
  }

  // Проверка offset
  if (options.offset && typeof options.offset !== "number") {
    throw new Error("offset должен быть числом");
  }

  // Проверка tolerance
  if (options.tolerance && typeof options.tolerance !== "number") {
    throw new Error("tolerance должен быть числом");
  }

  return true;
}

Использование:

validateHeadroomOptions(element, options);
const headroom = new Headroom(element, options);

Типизация и современные подходы

При использовании TypeScript проверка частично переносится на этап компиляции:

interface HeadroomOptions {
  offset?: number | { up: number; down: number };
  tolerance?: number | { up: number; down: number };
  classes?: Record<string, string>;
  scroller?: HTMLElement | Window;
}

Однако runtime-проверка остаётся необходимой, так как данные могут поступать из внешних источников.


Частые ошибки при отсутствии валидации

  • Передача строки вместо элемента → ошибка undefined is not a function
  • Неверный тип tolerance → некорректная реакция на прокрутку
  • Некорректный scroller → отсутствие реакции на scroll
  • Неправильные callback → silent failure (функции не вызываются)

Практика безопасной инициализации

function initHeadroom(selector, options) {
  const element = document.querySelector(selector);

  if (!element) {
    console.warn("Элемент не найден:", selector);
    return;
  }

  try {
    validateHeadroomOptions(element, options);
    const headroom = new Headroom(element, options);
    headroom.init();
  } catch (e) {
    console.error("Ошибка инициализации Headroom:", e.message);
  }
}

Рекомендации по проектированию

  • Проверка должна выполняться до создания экземпляра
  • Ошибки должны быть максимально информативными
  • Использование дефолтов снижает вероятность сбоев
  • В production предпочтительнее мягкая деградация
  • Валидация должна быть изолирована в отдельный слой

Расширенная валидация

В сложных приложениях может использоваться схема-валидация:

function isNumber(value) {
  return typeof value === "number" && !isNaN(value);
}

function validateOffset(offset) {
  if (isNumber(offset)) return true;

  if (
    typeof offset === "object" &&
    isNumber(offset.up) &&
    isNumber(offset.down)
  ) {
    return true;
  }

  return false;
}

Итоговая структура проверки

  1. Проверка существования элемента
  2. Проверка типа элемента
  3. Проверка типа options
  4. Проверка каждого свойства options
  5. Применение значений по умолчанию
  6. Обработка ошибок

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