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 облегчает написание декларативного кода при работе с пользовательскими интерфейсами.