О пользе велосипедов


Изобретать велосипеды не только вредно, но и полезно. Если вы не пытаетесь продать свою поделку.

Когда делаешь что-то своё, с нуля, на коленке — есть шанс разобраться в деталях, в том, как это работает (или не работает). Возьмём пример из строительства — можно быстро и недорого строить типовые дома из типовых компонентов. Но что делать, если нужно построить что-то уникальное (башню Федерации, например), а ты умеешь только сочленять бетонные панели? С другой стороны, большинство не в состоянии платить сотни тысяч миллионов за дворец с башенками, когда нужно просто где-то жить. Только вот придворные строители в случае великой нужды могут и хрущёбы собрать, но не наоборот.

Своё, родное

Иногда на досуге я пишу что-нибудь с нуля, чтобы научиться новому. Вчера решил запилить простенькую карусель с зацикленной листалкой (тысячи их). При этом, нужно чтобы листание происходило как вперёд, так и назад.

Делаю три функции:

function showPhoto(options) {
}

function showNextPhoto() {
    return slidePhoto()
}

function showPrevPhoto() {
    return slidePhoto({reverse: true})
}

Всю работу будем выполнять внутри slidePhoto(), выбирая номер следующего фото в зависимости от свойства reverse.

function showPhoto(options) {
    options = options || {reverse: false};
    var images = []; // не важно, как мы получаем этот массив
    var current; // также не важно, откуда мы берём этот индекс

    if (options.reverse) {
        // показать предыдущую
    } else {
        // показать следующую
    }
}

Теперь дело за малым — выбрать следующее фото, если текущее не последнее (первое в случае реверса), в противно случае взять первое фото из коллекции (или наоборот, последнее).

Костотряс

Мне совершенно не понравился тупой способ с условным выражением:

if (options.reverse) {
    current += 1;
    if (current === images.length) {
        current = 0;
    }
} else {
    if (current === 0) {
        current = images.length;
    }
    current -= 1;
}

Получилось очень громоздко, правда?

Старт-шоссе

Я стал думать, как всё это можно упростить. И придумал, но не до конца.

if (options.reverse) {
    current = (current + 1) % images.length;
}

Вместо четырёх строчек — одна. Так намного лучше, а кроме того, нет лишнего ветвления кода, что лучше вдвойне.

Но вот как быть с проходом в обратную сторону — я так и не решил. Можно было бы что-то сделать с [].reverse(), но этот метод разворачивает исходный массива, а не возвращает его развёрнутую копию.

Заключение

Можно изобрести велосипед, и набить собственных шишек. А можно спросить совета у те, кто уже запорол не один десяток стальных труб. Спрашиваю — как быть с проходом в обратную сторону-то? Чую, должно быть простое и элегантное решение.