JavaScript для Solid¶
Вы только начинаете осваивать фронтенд-фреймворки или возвращаетесь к JavaScript после нескольких лет работы? Здесь мы расскажем о наиболее важных возможностях и паттернах JavaScript, которые вам необходимо знать. JavaScript - гибкий язык, и существует множество подходов к его написанию, поэтому это не окончательное руководство для всех кодовых баз JavaScript, а руководство по "лучшим практикам" работы с Solid.
Избегайте этих ключевых слов¶
Когда вы только начинаете писать на современном JavaScript, у вас может возникнуть соблазн использовать одно из этих ключевых слов:
1 | |
Хорошее правило - избегать их. Без них можно построить любое приложение Solid, они добавляют неоправданную сложность в код, и для них есть замена, о которой мы поговорим ниже. Есть несколько случайных случаев использования this, о которых мы расскажем позже в документации. А некоторые продвинутые пользователи строят свои системы с использованием class, но не прислушиваются к нашим советам.
let и const¶
Раньше в JavaScript для объявления переменной можно было использовать var. В современном JavaScript есть два ключевых слова для объявления переменных: let и const. const объявляет переменную, которая никогда не будет установлена в какое-либо другое значение, а let объявляет переменную, которая может быть присвоена чему-либо другому.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
При работе с объектами и массивами гораздо чаще используется const, чем let, поскольку обычно требуется мутировать объект, а не переприсваивать переменную.
По умолчанию используется const. Объявляйте ее с помощью let только в том случае, если обнаружите, что впоследствии переменную необходимо переназначить. Таким образом, ваши намерения будут понятны читателям.
Vite и импорт ES6¶
До появления современных цепочек инструментов для веб-разработки мы "импортировали" несколько JavaScript-файлов, включая в HTML теги script.
1 2 | |
Это было непросто, поскольку необходимо было убедиться, что файл выполняется только после загрузки всех его зависимостей - порядок тегов сценария имел значение, и все это приходилось декларировать в HTML, а не в JavaScript, где использовались зависимости.
Такие средства разработки, как Vite, позволяют использовать более эффективный подход к импорту JavaScript. Vite - это сервер разработки и средство пакетирования: он выполняет ваш код локально, предоставляя такие возможности, как автоматическая перезагрузка, что облегчает разработку проекта. Когда вы готовы развернуть свой сайт, он "собирает" ваш код, оптимизируя его и разделяя JavaScript на множество тегов сценариев.
При написании наших проектов Solid мы используем подход к импорту, основанный на JavaScript, который был представлен в версии языка ES6. Если вы еще не знакомы с этим, обязательно ознакомьтесь с полной MDN-документацией, но вот краткий пример для ознакомления:
1 2 3 4 5 6 7 8 9 10 11 | |
Фабричные функции и замыкания¶
Существует множество способов объектно-ориентированного программирования на JavaScript, но наиболее распространенным из них, который можно встретить наряду с Solid, является техника определения функции, возвращающей объект.
1 2 3 4 5 6 7 8 9 10 11 12 | |
Поскольку функции в JavaScript можно передавать как любые другие значения (т.е. JavaScript имеет функции первого класса), объект, созданный фабричной функцией, может иметь свои собственные функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Обратите внимание, что функция drive использует значение make, которое было параметром внешней функции. В дальнейшем, когда вызывается myCar.drive(), она "запоминает" значение make. Это называется закрытием, поскольку значение, находящееся вне функции, было "вложено" в функцию, чтобы она могла использовать его в дальнейшем.
Мы можем использовать эти идеи для написания фабрик, непосредственно возвращающих функции:
1 2 3 4 5 6 7 8 | |
Деструктуризация¶
В JavaScript принято передавать объекты в качестве аргументов:
1 2 3 4 5 6 7 8 9 10 11 | |
Если мы знаем, что эти три свойства (screenWidth, screenHeight и multiplayer) присутствуют у объекта, то мы можем "деструктурировать" его и избавить себя от повторения имени объекта:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Мы также можем деструктурировать массивы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Деструктуризация позволяет нам делать много трюков, и вы часто будете видеть ее в Solid.
Шаблонные литералы¶
Мы можем упростить вывод на консоль в предыдущем примере, используя шаблонные литералы:
1 2 3 | |
Шаблонные литералы также позволяют создавать многострочные строки без необходимости вручную вставлять символ \n:
1 2 3 4 5 | |
Некоторые инструменты в экосистеме Solid используют tagged templates, которые позволяют определить функцию, работающую с литералом шаблона и любыми включенными в него переменными. Это позволяет легко придать строкам особую функциональность. Например, при использовании Solid без JSX используется тэгированный шаблон html:
1 2 3 4 5 6 7 | |
Стрелочные функции¶
В JavaScript существует множество способов объявления функции. Вот большинство из них:
-
1 2 3
function areaOfCircle(radius) { return radius * Math.PI ** 2; } -
1 2 3 4 5
const utils = { areaOfCircle(radius) { return radius * Math.PI ** 2; }, }; -
1 2 3
const areaOfCircle = function (radius) { return radius * Math.PI ** 2; }; -
1 2 3 4 5 6 7
const areaOfCircle = (radius) => { return radius * Math.PI ** 2; }; // Or the shorthand if you only have one line of code // in the function body: const areaOfCircle = (radius) => radius * Math.PI ** 2;
Между этими объявлениями есть нюансы - например, добавление console.log(this); внутри каждого из них - но большинство из них не имеют отношения к повседневной работе с Solid (если интересно, посмотрите эту подробную статью).
Если вы сомневаетесь, используйте функцию-стрелку (пример №4). При условии, что вы следуете предыдущему совету и не используете ключевое слово this, разницы между стрелочной функцией и функциональным выражением не будет.
Функции как аргументы¶
Ранее мы рассмотрели, как можно вернуть функцию из функции. Функцию также можно принимать в качестве аргумента функции:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Многие функции, встроенные в JavaScript (и многие, поставляемые с Solid), принимают аргумент функции. Приведенная выше функция действительно является встроенной в массивы JavaScript:
1 2 3 4 5 | |
Другим распространенным примером является встроенный метод map. Он принимает в качестве аргумента функцию, которая сопоставляет текущий элемент массива с новым результатом:
1 2 3 4 | |
Декларативный и императивный код¶
Методы массивов JavaScript, такие как map (и другие, такие как reduce и filter), могут заменить циклы, которые вы можете сделать с помощью for или while. Эти традиционные циклы называются "императивными" - в них пошагово описывается, как выполнить то или иное действие:
1 2 3 4 5 6 7 8 | |
Использование методов массивов JavaScript позволяет получить более "декларативный" код, в котором указывается что нужно сделать, но не указываются все детали того, как это сделать.
1 2 3 4 5 | |
Здесь мы сделали то же самое в одной строке кода с помощью метода массива filter, который принимает функцию и возвращает новый массив, содержащий только те элементы, которые возвращают true при передаче функции.
Когда мы говорим, что пишем "декларативный код", мы имеем в виду, что используем абстракции для написания кода, который более упорядочен: больше сосредоточен на том, что мы пытаемся сделать, чем на том, как именно. Использование фильтра позволяет нам писать меньше "шаблонного" зацикленного кода, а вместо этого сосредоточиться на основной функциональности, которая нам нужна. Код проще читать: циклы for могут использоваться для самых разных целей, но всякий раз, когда вы видите filter, вы знаете, что целью цикла является игнорирование некоторых элементов в массиве.
HTML - отличный пример декларативного способа написания: вы указываете, какой должна быть структура, а не то, как она должна быть собрана или отображена. Как мы надеемся показать в этом руководстве, Solid облегчает написание декларативного кода при работе с пользовательскими интерфейсами.