Возможно, вы слышали о разнице между декларативным и императивным кодом. Но вам все еще неясно. К концу этой статьи вы объявите себя экспертом!

Декларативный код сообщает что. Императив сообщает как. Императивный код более подробный. Антропоморфизированная тетя Клара - южная женщина, которая декларирует вещи. Она восклицает: «Это печенье такое пушистое!» Тетя Груша раньше была школьной учительницей. Вместо того чтобы констатировать факт, она дает инструкции. Подробная инструкция. Через некоторое время ваши глаза начинают пересекаться. Любое сходство с вашими родственниками чисто случайно.

Возможно, вы открывали капот своей машины, чтобы покопаться во внутренностях один или два раза. Тем не менее, вы можете управлять автомобилем, не зная, как он устроен внутри. Вы также можете писать код Ruby годами, ничего не зная о коде C, который скрывается под ним.

Как и во многих вещах, есть спектр. Декларативный код, с одной стороны, имеет тенденцию быть более кратким и высокоуровневым. Императивный код часто выполняется быстрее, но при этом более подробный.

Как лучше всего? Как и в большинстве случаев, здесь есть компромиссы. Если вы оптимизируете читаемость, декларативный код - ваш друг. В некоторых случаях императив лучше. Обычно более необходим более низкоуровневый код, оптимизированный для быстрого выполнения. Как правило, чем ближе вы подходите к делу, тем меньше вы можете полагаться на высокоуровневый код. Вы можете больше думать о сборке мусора, чем о удобочитаемости.

У вас так много возможностей с JavaScript, что прекрасно / ужасно. Вы можете написать код, немного похожий на Java примерно 90-х годов. Подробный код изобилует циклами for и точкой с запятой. Но, конечно, везде есть слово прототип, и никаких сильных типов. Однострочные фабричные методы - более современный стиль. Функции больше не должны произносить слово функция. Толстые стрелки и неявный возврат для однострочных функций - это особенности ES6. Вы также можете избежать циклов for, используя многие встроенные методы массива.

Я часто копаюсь в Github, чтобы узнать, что основные библиотеки делают с JavaScript. Во многих библиотеках, которые я использую, есть императивный код. Тем не менее, если я вижу много императивного кода в проверяемом мной PR, я обычно спрашиваю, может ли быть более чистый способ. Как фронтенд-разработчик, мы чаще всего хотим, чтобы читабельность была превыше всего.

А теперь, без лишних слов, канонический пример! Мы заменяем циклы for на изящные методы JavaScript Array reduce (), map () и filter ().

Обратите внимание, что в нашем декларативном примере используется синтаксис жирной стрелки ES6 и reduce (). Функция reduce () принимает коллекцию и функцию в качестве аргумента. Функция как аргумент - довольно распространенная тема, когда дело доходит до итерации функциональным способом. Это лаконичный способ сказать возьми каждый элемент и сделай с ним вот что. Это также называется закрытием, поскольку внутренняя функция закрывает переменные во внешней функции.

Эта внутренняя функция принимает два аргумента. Это текущий элемент и аккумулятор (здесь a и b). Каждый раз, когда вы хотите объединить множество вещей в одно целое, это чистый способ сделать это. Вы также можете передать начальную точку своего редуктора. По умолчанию он равен 0, поэтому, если вы ничего не передаете, вашим начальным элементом будет 0. Это означает, что вы намереваетесь уменьшить до целого числа. Но вы также можете сократить до массива, передав пустой массив.

Оба способа написания функции sumItUp () дают одинаковые результаты. Второй использует reduce (), чтобы сократить количество необходимых строк кода. Под reduce () вы, скорее всего, увидите цикл for. Итерация по массиву для получения единственного значения - распространенная проблема. Умный инженер сказал: «Мы должны сделать это многоразовым, чтобы никогда больше не писать!»

Сокращение одной функции до одной строки кода может показаться несерьезным. Это будет иметь большое влияние на многие строки кода. Краткий код оставляет больше возможностей для решения интересных задач. Однако есть грань между элегантным и умным. Попытка сжать все в одну строку не всегда сделает ее более удобочитаемой или эффективной.

Давайте посмотрим на другой пример. Как насчет выравнивания массива?

Вы также можете сократить это до одной строки! Обратите внимание на переданный пустой массив, чтобы уменьшить его базовое значение.

Для многомерного массива вам все равно нужно будет его рекурсивно сгладить.

Здесь я хотел бы сделать небольшой объезд. Рекурсивное решение может быть элегантным. Это также может быть менее эффективным. По мере того, как ваш ввод увеличивается в размере, каждый рекурсивный проход пожирает память, как голодный призрак. Двигатель V8 ограничивает объем памяти, выделяемой каждому процессу. При рекурсии вы рискуете создать ужасное исключение стекового фрейма. Подробнее об этом в другой раз!

Так или иначе, мы обсуждали reduce (), filter () и map ().

Мы говорили о reduce (), поэтому давайте посмотрим на filter (). Вы давали простую задачу. Учитывая кучу волшебников, выберите только тех, кто принадлежит к дому Хаффлпафф.

Или вы можете использовать filter () для однострочного решения.

Теперь обсудим map (). Это оказывается полезной абстракцией при написании пользовательского интерфейса в React. Map () берет каждый элемент в коллекции и сопоставляет его с другим значением с помощью внутренней функции.

Мы также можем отобразить () некоторое волнение на наших домах волшебников.

Вы также можете использовать map () для извлечения элементов из более крупного набора данных. Часто REST API возвращают исчерпывающий набор данных, но вам нужно всего два элемента. Вы можете отобразить только необходимые значения.

Обратите внимание, что map () создает новый массив. Это сохраняет целостность данных, поскольку сохраняет исходный массив. Часто самые сложные части одностраничных приложений связаны с управлением состоянием. Целостность данных побеждает.

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

Очень распространенный вариант использования map () в React - прикрепление JSX к входным данным в шаблоне.

Мы можем назначить каждому дому цвет, сопоставив класс CSS с его элементом на основе имени дома.

Разделы мастеров, размещенные с сетками CSS, изменят размер, чтобы соответствовать любому контейнеру. Загляните в исходники на Github, чтобы в дальнейшем насладиться волшебством.

С map () вам понадобится совсем немного кода для создания динамической сетки. Здесь мы используем фикстуру или плоский файл для имитации наших данных. Этот базовый шаблон будет работать, если ваши данные также поступают из удаленного источника. Помните, что вы также можете использовать map () для выбора элементов из большого набора данных, поступающих из удаленного API.

Представьте, что вы делаете это с помощью JQuery! Было бы много выбора и добавления. Вам нужно будет указать, где что-то прикреплено, а затем сгенерировать элементы DOM с конкатенацией строк. Кроме того, для получения адаптивной сетки потребуется Bootstrap или много строк CSS. Так что любое изменение ваших стилей приведет к огромному переписыванию.

Что, если вы хотите добавить интерактивности этой сетке мастера? Давайте добавим простой обработчик кликов к каждому блоку div, чтобы при нажатии на него что-нибудь происходило. На данный момент нас не слишком беспокоит, что происходит. Давайте сделаем это мастером выбора. Это эгалитарное общество волшебников, поэтому они по очереди становятся избранными. Никто не должен нести это бремя в одиночку!

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

Наш новый компонент - это функция. Управление состоянием выполняется в другом месте, поэтому компонент будет излишним. Обновленное состояние является аргументом.

Мы объявляем нашу функцию с помощью const. Значит, он неизменен? По правде говоря, нет. Мы знаем, что с теми же входными данными он вернет тот же результат, поскольку мы никогда не изменяем там состояние. Когда мы позже займемся решением государственных проблем, в нашей кодовой базе будет более узкая область джунглей.

Теперь мы можем выбрать любого мастера в качестве нового избранного. Мы также можем добавить к их квадрату класс selected, чтобы визуально выделить их. Пуф! Map () снова делает выбор мастером забавным.

Что, если мы хотим обыскать волшебников? Ранее мы писали функцию для фильтрации только волшебников из Хаффлпаффа. Мы можем адаптировать его для элементарного поиска. Я бы не рекомендовал это в производственном приложении!

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

С помощью волшебного рожка для ушей я слышу твои мысли, нежный читатель. Вы правы, эта форма поиска должна быть отдельным компонентом. Раз уж вы так думали, я оставлю это вам в качестве упражнения.

Что ж, на сегодня все. Я надеюсь, что это было полезно. Не стесняйтесь обращаться с комментариями и вопросами.