@boga-net

Как грамотно и красиво сформировать вложенность функций? Структура кода?

Всем привет. Учу js, практикуюсь по маленьку. Придумал идею и теперь пытаюсь её реализовать. Код стал разрастаться, пухнуть и визуально в нём становится всё труднее ориентироваться. Стало много функций, а я к такому ещё не привык. Задумался о красивом, структурированном, читабельном коде, чтобы в дальнейшем я сразу понимал, как начинать грамотно создавать проект. И чтобы потом уже не переделывать. Мало ли, вдруг кто будет читать мой код. Да и вообще, надо начинать делать красиво и правильно

Допустим, у меня есть последовательность действий и я разбил это на функции для удобства правки и вызова (чтобы не ждать выполнение первой, но увидеть работу второй)

1. Начальный экран с анимацией
2. Стартовый экран, предвестник главной функции, какие-то настройки
3. Основная функция

В каждой из них содержатся ещё функции. В данный момент, в этих трёх функциях есть другие вложенные функции: как и их описание, так и их вызов. И вот здесь встал вопрос, как правильно всё это организовать. Вызывать вложенные функции нужно из этих функций, но нужно ли их там описывать ? Ниже пример

Как лучше поступить :
1. Описывать функции в таких логических блоках кода, как ниже ? То есть функция logoFunc выполнится один раз в самом начале и про неё можно спокойно забыть, как и про все функции, которая она вызывает. И логично запихнуть в неё описание функций, которые ей нужны. И в текстовом редакторе легче - свернул одну функцию и скрылись все вложенные

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

function starScreen() {
  logoFunc();
  settingsFunc();
  mainFunc();
};

function logoFunc() {

  logoFunc__1();
  logoFunc__2();

  function logoFunc__1() {}

  function logoFunc__2() {

    logoFunc__2__inner();
    logo_show();
    logo_hide();

    function logoFunc__2__inner() {

      logoFunc__2__inner__MEGA__inner();

      function logoFunc__2__inner__MEGA__inner() {}
    };

    function logo_show(){};
    function logo_hide(){};
  };
};


Или же всё таки такой подход лучше/читабельней/практичней/грамотней и т.д. ?

function starScreen() {
  logoFunc();
  settingsFunc();
  mainFunc();
};

function logoFunc() {
  logoFunc__1();
  logoFunc__2(); 
};

function logoFunc__1() {}

function logoFunc__2() {
  logoFunc__2__inner();
  logo_show();
  logo_hide();
};

function logo_show(){};

function logo_hide(){};

function logoFunc__2__inner() {
  logoFunc__2__inner__MEGA__inner();
};

function logoFunc__2__inner__MEGA__inner() {}


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

Так же хочу минимизировать код функций, сделать более красивым, лаконичным. Допустим, вот кусок реального кода :

// Поворот кнопок звука по оси Y
    $('.sounds-wrapper').on('mouseenter', function() {
      $(this).addClass('sounds-wrapper-active');
    });
    $('.sounds-wrapper').on('mouseleave', function() {
      $(this).removeClass('sounds-wrapper-active');
    });

    // Наведение на кнопки звука и их поворот
    $('#music-bottom').on('mouseenter', '.sounds-btn-left', function() {
      $(this).closest('.sounds-wrapper').addClass('sounds-btn-hover-left');
    });
    $('#music-bottom').on('mouseleave', '.sounds-btn-left', function() {
      $(this).closest('.sounds-wrapper').removeClass('sounds-btn-hover-left');
    });
    $('#sound-bottom').on('mouseenter', '.sounds-btn-right', function() {
      $(this).closest('.sounds-wrapper').addClass('sounds-btn-hover-right');
    });
    $('#sound-bottom').on('mouseleave', '.sounds-btn-right', function() {
      $(this).closest('.sounds-wrapper').removeClass('sounds-btn-hover-right');
    });

    // Переключение класса при клике на вкл/выкл
    $('#music-bottom').on('click', '.btn', function() {
      $('#music-bottom').find('.btn').removeClass('sounds-btn-active').addClass('sounds-btn-not-active');
      $(this).addClass('sounds-btn-active');
    });
    $('#sound-bottom').on('click', '.btn', function() {
      $('#sound-bottom').find('.btn').removeClass('sounds-btn-active').addClass('sounds-btn-not-active');
      $(this).addClass('sounds-btn-active');


Здесь всё понятно, что происходит и зачем. Практично ли оставлять так ? Приемлем для вас такой код ? Или вы бы сделали что-то с event.target, чтобы не дублировать некоторые строчки кода ? Да, $('#music-bottom') можно было добавить в переменную, например, "musicBottom" и обращаться к ней. В этом случае я специально так оставил, чтобы сразу было понятно, на каком элементе обрабатываются события. И вообще, в реальной практике, вот в таком случае, есть ли смысл создавать две лишние переменные (soundBottom и musicBottom) или лучше оставить так ?

Всем спасибо, всем низкий поклон
  • Вопрос задан
  • 243 просмотра
Пригласить эксперта
Ответы на вопрос 3
BRAGA96
@BRAGA96
По поводу оптимизации.
1. На один элемент можно вешать сразу несколько событий передав их объектом в методе .on
$('.sounds-wrapper').on({
	mouseenter: function() {
		$(this).addClass('sounds-wrapper-active');
	},
	mouseleave: function() {
		$(this).removeClass('sounds-wrapper-active');
	}
});

2. Вместо такой конструкции
$('#music-bottom').on('mouseenter', '.sounds-btn-left', function() {});

Лучше передать контекст
$('.sounds-btn-left', $('#music-bottom')).on('mouseenter', function() {});

3. Вместо mouseenter и mouseleave можно использовать hover
Первый аргумент принимает функцию если на элемент навели, а второй если мышь убрали
$('#sound-bottom').on('hover', function() {
	$(this).closest('.sounds-wrapper').addClass('sounds-btn-hover-right');
}, function() {
	$(this).closest('.sounds-wrapper').removeClass('sounds-btn-hover-right');
});

4. Когда будете создавать переменные, чтобы кэшировать элементы, то начините название с $, например $musicBottom. Так Вам и другим людям, которые будут смотреть Ваш код будет понятно что в этой переменной jQuery DOM элемент.
Ответ написан
rim89
@rim89
программист-велосипедист
И чтобы потом уже не переделывать

Нет предела совершенству

Как лучше поступить

смотреть в сторону ООП и SOLID
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Добавление/удаление класса по мышиному событию лучше доверить CSS и использовать псевдокласс :hover

Вместо подобных пар
$('.sounds-wrapper').on('mouseenter', function() {
      $(this).addClass('sounds-wrapper-active');
    });
    $('.sounds-wrapper').on('mouseleave', function() {
      $(this).removeClass('sounds-wrapper-active');
    });


лучше назначить свойства для
.sounds-wrapper { ... }
.sounds-wrapper:hover { ... здесь то, что раньше было в .sounds-wrapper-active }
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы