Jsqry — библиотека для запросов к JS объектам и массивам

Представляю вашему вниманию небольшую js-библиотеку Jsqry.
Проще всего проиллюстрировать её назначение следующим примером.

До:

var name;
for (var i = 0; i < users.length; i++) {
    if (users[i].id == 123) {
        name = users[i].name;
        break;
    }
}

После:

var name = one(users, '[_.id==?].name', 123);

Библиотечка позволяет извлекать информацию из объектов/массивов в одну строку, используя несложный язык запросов, вместо написания циклов (подчас вложенных).

По сути, она реализует всего две функции:


  • query — для возвращения списка результатов и
  • one — для возвращения первого найденного результата.

Список возможностей включает:


  1. Фильтрацию
  2. Трансформацию
  3. Индексы/срезы в стиле Python

Библиотека появилась спонтанно в одном проекте, построенном на модном ныне подходе одностраничного приложения. Мы загружаем один большой JSON, части которого затем используются для рендеринга на клиенте разных представлений сайта. И вот для выдирания этих самых частей и захотелось более удобного способа. Затем, впрочем, библиотека оказалась востребована и в других случаях.

Поясню немного по функционалу. Запрос в общем случае может иметь вид

field1.field2[ condition or index or slice ].field3{ transformation }.field4

Тут:


  • field1.field2.field3… — обычный доступ к полям объектов, как в js
  • [ condition ] — фильтрация
  • [ index ] — доступ по индексу, тоже как в js
  • [ from: to: step ] — срезы в стиле Python
  • { transformation } — преобразование объектов

На condition и transformation стоит остановиться подробнее.
На самом деле тут все очень просто. Достаточно понять, что каждое выражение внутри квадратных/фигурных скобок при выполнении заменяется на функцию по такому принципу:

condition_or_transformation ⟶ function (_, i) { return condition_or_transformation }

(тут _ — значение передаваемого элемента, i — его индекс).

Пример:

query([1,2,3,4,5],'[_>2]{_+10}') // [13, 14, 15]

Также поддерживаются параметризация запроса:

query([1,2,3,4,5],'[_>?]{_+?}', 2, 10) // [13, 14, 15] 

Комбинируя эти возможности можно строить весьма сложные и гибкие запросы. Больше примеров использования можно посмотреть тут.

Из интересного в реализации — AST дерево запроса кешируется, что придает библиотеке скорости.

Разумеется, моя библиотека не уникальна в своём роде. Стоит привести «небольшой» список аналогов:

Зачем еще одна библиотека? На самом деле, она поддерживает не весь возможный спектр типов запросов, а только то что было нужно в нашем проекте в большинстве случаев. За счет этого простота и скорость. Также, чрезвычайно простой API, вдохновленный подходом JQuery.

Буду рад выслушать критику и предложения по улучшению.

© Habrahabr.ru