Category: Backend

14
Апр
2021

☕ Лучшие фреймворки Node.js в 2021 году

Node.js – популярная программная платформа с открытым исходным кодом, превращающая JavaScript из узкоспециализированного инструмента для веба в универсальный язык программирования для создания кросс-платформенных приложений. В небольшом обз…

12
Апр
2021

Как заставить сервер на Flask исполнять мой блок кода Python?

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

12
Апр
2021

Как заставить сервер на Flask исполнять мой блок кода Python?

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

12
Апр
2021

Как заставить сервер на Flask исполнять мой блок кода Python?

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

11
Апр
2021

Нужна помощь по JavaScript очень

Как правильно реализовать галерею работ на одностраничном сайте? Где каждый пример выполненных работ должен выводить свои картинки для слайдера и другую информацию. Можно это реализовать, не прибегая к backend?

07
Апр
2021

Как спрятать ключи API?

У меня есть несколько строковых ключей (ключи api, id магазина и т.п.), которые мне нужны в JS, но которые не должен видеть юзер (логично). Естественно, просто записать их в скрипт – нельзя, ведь так их легко найти. Я думаю, записать их в …

03
Апр
2021

Почему неправильно работает редирект .htaccess? PHP

Почему при вводе любого символа в каталоге .htaccess работает нормально, а на других страницах по типу index.php – нет?
Скриншот ниже: Есть редирект на 404 страницу

Скриншот ниже: Нету редиректа на 404 страницу

Сам .htaccess

24
Мар
2021

artifactId и version подсвечивается красным в Maven

вот cкрин ->

Пытаюсь сконфигурировать Spring MVC в Maven. Но artifactId и version подсвечивается красным. И ничего не добавляется. Подскажите, что делать? По возможности скиньте ссылку на ресурс, который решает мою проблему.

<proje…

24
Мар
2021

Parse error: syntax error, unexpected namespaced name "implements\IteratorAggregate", expecting "{"

Хочу сделать систему регистрации на PHP и столкнулся с проблемой. Использую RedBean PHP и вот именно в файле rb.php походу есть ошибка. Когда запускаю index.php выводит следующее:
Parse error: syntax error, unexpected namespaced name &quot…

24
Мар
2021

Parse error: syntax error, unexpected namespaced name "implements\IteratorAggregate", expecting "{"

Хочу сделать систему регистрации на PHP и столкнулся с проблемой. Использую RedBean PHP и вот именно в файле rb.php походу есть ошибка. Когда запускаю index.php выводит следующее:
Parse error: syntax error, unexpected namespaced name &quot…

21
Мар
2021

☕ 5 продвинутых советов по повышению производительности Vue

Рассмотрим советы и рекомендации по оптимизации памяти и уменьшению повторного рендеринга, которые могут быть применены к любому приложению на vue2/vue3.

Перевод публикуется с сокращениями, автор оригинальной статьи
Alexey Kuznetsov.

Есть два созданных специально для этой статьи репозитория
(для vue2 и vue3):


(Deep) наблюдатели за объектами

Правило простое: не
используйте глубокий модификатор и не следите за переменными отличного от примитивного
типа. Рассмотрим некоторые элементы массива из хранилища vuex, каждый из которых может иметь статус checked. Сохраним отдельно связанное с клиентом свойство IsChecked.
Предположим, что есть геттер, который объединяет данные элемента и свойство IsChecked:

        export const state = () => ({
  items: [{ id: 1, name: 'First' }, { id: 2, name: 'Second' }],
  checkedItemIds: [1, 2]
})

export const getters = {
  extendedItems (state) {
    return state.items.map(item => ({
      ...item,
      isChecked: state.checkedItemIds.includes(item.id)
    }))
  }
}
    

Элементы могут быть
переупорядочены, и полученный порядок должен быть отправлен в бекенд:

        export default class ItemList extends Vue {
  computed: {
    extendedItems () { return this.$store.getters.extendedItems },
    itemIds () { return this.extendedItems.map(item => item.id) }
  },
  watch: {
    itemIds () {
      console.log('Saving new items order...', this.itemIds) 
    }
  }
}
    

Затем checking/unchecking элемента организует
неправильное срабатывание вызова itemIds
watcher
. Это происходит, поскольку каждый раз, когда элемент становится checked, геттер создает новый объект
для каждого элемента. По этой причине произойдет вычисление itemIds для пересоздания нового массива, несмотря на то, что он уже имеет те же значения в том же порядке: [1, 2, 3] !==
[1, 2, 3]
.

Решение состоит в том, чтобы избежать использования наблюдателей для переменных объектного типа. Каждый раз, когда необходим какой-то наблюдатель для запуска, мы должны построить отдельный примитивный тип, вычисленный специально для этого случая.

Например, если нужно пронаблюдать за массивом элементов со свойствами {id,
name, userId}
, можно поступить следующим образом:

        computed: {
  itemsTrigger () { 
    return JSON.stringify(items.map(item => ({ 
      id: item.id, 
      title: item.title, 
      userId: item.userId 
    }))) 
  }
},
watch: {
  itemsTrigger () {
    // Не используйте здесь JSON.parse 
            – дешевле использовать исходный массив this.item;
  }
}
    

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

Демонстрационные материалы для vue2
и
vue3.

Ограничение реактивности с помощью Object.freeze

Этот совет эффективен
для приложения vue2 и способен уменьшить использование памяти
на 50%. Иногда
vuex
содержит много редко изменяющихся данных, особенно если там хранится кэш
ответов api (актуально для приложений
ssr).
По умолчанию vue рекурсивно наблюдает за каждым свойством объекта. Иногда лучше
потерять реактивность свойств объекта, сохранив вместо этого немного
памяти:

        // Вместо этого:
state: () => ({
  items: []
}),
mutations: {
  setItems (state, items) {
    state.items = items
  },
  markItemCompleted (state, itemId) {
    const item = state.items.find(item => item.id === itemId)
    if (item) {
      item.completed = true
    }
  }
}

// Делаем так:
state: () => ({
  items: []
}),
mutations: {
  setItems (state, items) {
    state.items = items.map(item => Object.freeze(item))
  },
  markItemCompleted (state, itemId) {
    const itemIndex = state.items.find(item => item.id === itemId)
    if (itemIndex !== -1) {
      // Здесь невозможно обновить item.completed = true
      // потому что объект заморожен. 
      // Нам нужно пересоздать весь объект.
      const newItem = {
        ...state.items[itemIndex],
        completed: true
      }
      state.items.splice(itemIndex, 1, Object.freeze(newItem))
    }
  }
}
    

Примеры для vue2
и
vue3
. Поскольку vue3 имеет другую систему реактивности, эффект такой оптимизации менее
релевантен. Кроме того общее использование памяти в
vue3 намного ниже, чем в vue2 (это 80 Мб для vue2 и 15 Мб для примеров vue3). К
сожалению, у vuex4 есть проблемы с очисткой (вы можете увидеть это данном
примере), но разработчики обещают исправить ситуацию.

Функциональные геттеры

Зачастую это упускается
из виду в
документации: функциональные геттеры не кэшируются. Этот код будет запускать state.items.find
каждый раз, когда он вызывается:

        // Vuex: 
getters: {
  itemById: (state) => (itemId) => state.items.find(item => item.id === itemId)
}
...
// Некоторый <Item :item-id="itemId" /> component:
computed: {
  item () { return this.$store.getters.itemById(this.itemId) }
}
    

Такой код будет
создавать объект itemsByIds при первом вызове, а затем повторно использовать:

        getters: {
  itemByIds: (state) => state.items.reduce((out, item) => {
    out[item.id] = item
    return out
  }, {})
}
// Некоторый <Item :item-id="itemId" /> component:
computed: {
  item () { return this.$store.getters.itemsByIds[this.itemId] }
}
    

Примеры для vue2
и
vue3.

Распределение компонентов

Компонент – ключевая особенность всей экосистемы vue, относящаяся к производительности. Понимание жизненного цикла компонента и правил обновления имеет важное значение для построения эффективного приложения. Когда начинаем работать с vue, мы пытаемся распределить код по компонентам. Например, если есть список повторяющихся записей, то хорошо бы переместить связанный с записью код в отдельный компонент.

Распределение
компонентов обеспечивает мощный механизм, дающий точный контроль над степенью детализации обновления. Это основная связанная с
производительностью функция. Рассмотрим следующий код:

        // Store:
export const getters = {
  extendedItems (state) {
    return state.items.map(item => ({
      ...item,
      isChecked: state.checkedItemIds.includes(item.id)
    }))
  },
  extendedItemsByIds (state, getters) {
    return getters.extendedItems.reduce((out, extendedItem) => {
      out[extendedItem.id] = extendedItem
      return out
    }, {})
  }
}

// App.vue:
<ItemById for="id in $store.state.ids" :key="id" :item-id="id />

// Item.vue:
<template>
  <div>{{ item.title }}</div>
</template>

<script>
export default {
  props: ['itemId'],
  computed: {
    item () { return this.$store.getters.extendedItemsByIds[this.itemId] }
  },
  updated () {
    console.count('Item updated')
  }
}
</script>
    

Это демо-версия: vue2,
vue3
.
Попробуйте переименовать, отметить или изменить порядок элементов. Любое предназначенное только для одного элемента обновление приведет к повторному
отображению других элементов в списке. Причина в том, что компонент <Item> ссылается на объект extendedItemsByIds, который перестраивается
при изменении любого свойства элемента.

Каждый компонент vue – это функция, которая предоставляет некоторый виртуальный DOM и кэширует результат в зависимости от его аргументов. Список аргументов определяется на этапе запуска и состоит из реквизитов и некоторых переменных в $store. Если аргумент является объектом, который перестраивается после обновления, кэширование не работает.

В первоначальной структуре
используется подход normalizr, а наш геттер extendedItems копирует свойства элемента вместо того, чтобы просто
ссылаться на исходный объект. Давайте это исправим:

        // Store:
export const state = () => ({
  ids: [],
  itemsByIds: {},
  checkedIds: []
})

export const getters = {
  extendedItems (state, getters) {
    return state.ids.map(id => ({
      id,
      item: state.itemsByIds[id],
      isChecked: state.checkedIds.includes(id)
    }))
  }
}

export const mutations = {
  renameItem (state, { id, title }) {
    const item = state.itemsByIds[id]
    if (item) {
      state.itemsByIds[id] = Object.freeze({
        ...item,
        title
      })
    }
  },
  setCheckedItemById (state, { id, isChecked }) {
    const index = state.checkedIds.indexOf(id)
    if (isChecked && index === -1) {
      state.checkedIds.push(id)
    } else if (!isChecked && index !== -1) {
      state.checkedIds.splice(index, 1)
    }
  }
}

// Items.vue:
<ItemWithRenameById2
  v-for="id in ids"
  :key="id"
  :item-id="id"
  @set-checked="setCheckedItemById({ id, isChecked: $event })"
  @rename="renameItem({ id, title: $event })"
/>


// Item.vue:
computed: {
  item () {
    return this.$store.state.itemsByIds[this.itemId]
  },
  isChecked () {
    return this.$store.state.checkedIds.includes(this.itemId)
  }
}
    

Этот код корректно
работает для переименования элемента (примеры vue2,
vue3
),
но checking/unchecking элемента
по-прежнему приводит к повторному рендерингу каждого, а переупорядочение
элементов работает в vue2, но не в vue3.

Последняя описанная
ситуация – это
предполагаемое поведение, но оно не задокументировано. Причина заключается в
ссылке на scope-переменную (id) в обработчиках событий @set-checked и @rename.
В vue3 scope-переменная в обработчике событий не может быть закэширована, что
означает – каждое обновление создает новую функцию события, вызывающую обновление
компонента. Это можно исправить, отправив подготовленное событие, содержащее
scope-переменную (id в нашем случае). Действие демонстрируется в
примере
для vue3.

Еще один способ
исправить вызванный ссылкой на scope-переменную рендеринг – указать все
события, которые компонент может обработать в новом свойстве vue3, называемом emits. Наш компонент ItemWithRenameById2 может работать с двумя событиями: @set-checked и @rename. Если добавить оба emits:
[‘set-checked’, ‘rename’]
, то
переупорядочение элементов начнет работать правильно. Вот подтверждение
для vue3.

Последнее, что нужно
исправить – это IsChecked. Он
ссылается на весь массив $store.state.checkedIds
(пытается найти там значение). Состояние элемента «checking» изменяет этот массив, поэтому каждый <Item> должен повторить поиск.
Это можно исправить, отправив IsChecked
как логическое свойство каждому компоненту <Item>
вместо поиска значения внутри:

        // Items.vue:
<Item
  v-for="extendedItem in extendedItems"
  :key="extendedItem.id"
  :item="extendedItem.item"
  :is-checked="extendedItem.isChecked"
  @set-checked="setCheckedItemById"
  @rename="renameItem"
/>
    

Примеры корректно
работающего решения для
vue2
и
vue3.

Директива IntersectionObserver

Иногда DOM сам по себе большой
и медленный. Можно использовать несколько методов для уменьшения его размера.
Например, диаграмма Ганта вычисляет положение и размер каждого элемента, и
легко пропустить элементы за пределами viewport-а. Есть один простой трюк
IntersectionObserver для случая, когда размеры неизвестны. Кстати, vuetify
имеет директиву v-intersect из коробки, но последняя создает отдельный
экземпляр IntersectionObserver, поэтому она не подходит для случая, когда нужно
мониторить много узлов.

Давайте рассмотрим примеры
(
vue2,
vue3
),
которые мы собираемся оптимизировать. Есть 100 записей (только 10 отображены на
экране). Каждая содержит тяжелый svg, который мигает каждые 500 мс. Вычислим
задержку между расчетным и реальным миганием, создадим один экземпляр
IntersectionObserver и пробросим его на каждый узел, который необходимо
наблюдать:

        export default {
  inserted (el, { value: observer }) {
    if (observer instanceof IntersectionObserver) {
      observer.observe(el)
    }
    el._intersectionObserver = observer
  },
  update (el, { value: newObserver }) {
    const oldObserver = el._intersectionObserver
    const isOldObserver = oldObserver instanceof IntersectionObserver
    const isNewObserver = newObserver instanceof IntersectionObserver
    if (!isOldObserver && !isNewObserver) || (isOldObserver && (oldObserver === newObserver)) {
      return false
    }
    if (isOldObserver) {
      oldObserver.unobserve(el)
      el._intersectionObserver = undefined
    }
    if (isNewObserver) {
      newObserver.observe(el)
      el._intersectionObserver = newObserver
    }
  },
  unbind (el) {
    if (el._intersectionObserver instanceof IntersectionObserver) {
      el._intersectionObserver.unobserve(el)
    }
    el._intersectionObserver = undefined
  }
}
    

Теперь мы знаем, какие
записи не видны – нам нужно их упростить. Можно определить некоторую
переменную в vue и заменить тяжелую часть упрощенным заполнителем. Важно
понимать, что инициализация сложных компонентов – та еще задачка. Может случиться, что страница будет лагать во время быстрой прокрутки, потому что делается слишком много тяжелых инициализаций. Практические эксперименты говорят, что
переключение на уровне css происходит быстро и незаметно. Можно просто
использовать css display: none для
каждого тяжелого svg за пределами viewport, что увеличит производительность:

        <template>
  <div 
    v-for="i in 100" 
    :key="i" 
    v-node-intersect="intersectionObserver"
    class="rr-intersectionable"
  >
    <Heavy />
  </div>
</template>

<script>
export default {
  data () {
    return {
      intersectionObserver: new IntersectionObserver(this.handleIntersections)
    }
  },
  methods: {
    handleIntersections (entries) {
      entries.forEach((entry) => {
        const className = 'rr-intersectionable--invisible'
        if (entry.isIntersecting) {
          entry.target.classList.remove(className)
        } else {
          entry.target.classList.add(className)
        }
      })
    }
  }
}
</script>

<style>
.rr-intersectionable--invisible .rr-heavy-part
  display: none
</style>
    

Заключение

Мы рассмотрели методы
оптимизации работы кода в приложениях
Vue, которые можно
и нужно применять в ваших текущих проектах. Правильная работа с памятью при
использовании компонентов и увесистых элементах viewport-а значительно улучшит
эффективность использования приложения и поднимет
UX. Удачи в обучении!

Дополнительные материалы:

20
Мар
2021

как правильно расположить на сервере бэк и фронт?

Я хочу написать REST api на PHP для фронтовой части моего сайта.
для этого я создал папку API на хостинге в которой планирую разместить PHP код. Это правильное решение?
Как сделать это верно?

11
Фев
2021

Yii2 Advanced с нуля до профи

Начала изучать yii2 advanced. Но никак не могу найти подходящие курсы, уроки чтобы прям пошагово по урокам было показано рассказано, все с нуля. Я полный ноль в фреймворках. Подскажите где найти нормальные курсы или уроки.

26
Янв
2021

🕸 Обучение веб-разработке: полезные сервисы, о которых в 2021 году должен знать каждый

Сервисы для обучения веб-разработке в открытом доступе позволяют освоить теорию и получить базовые практические навыки программирования. Мы пишем о них довольно часто – читайте обзор ресурсов, актуальных в 2021 году.

24
Янв
2021

JS. Авторизация и переход на следующую страницу

я решил для обучения написать небольшой сайт. Я набросал страничку авторизации. На сервере будет использоваться Node.js. После того, как я ввожу логин и пароль нажимается кнопка входа. Отправляется запрос login на сервер, на сервере провер…

18
Янв
2021

Хранение и работа с разными версиями документов в БД

Есть ли какой-то общепринятый подход хранения документов в РСУБД в виде json или xml,
при котором не нужно было бы проводить миграции при изменении структуры документов?
(Интересуют именно РСУБД, NoSQL базы не получилось протащить в проект…

13
Янв
2021

Всевозможные варианты из n-размерного масива JS

Здраствуйте! Есть масив который может содержать n количество масивов(в этом масиве может содержаться n количество елементов)
Пример
[[1,2,3,4],[5,6,7,8,9],[10,11,12,13,14,15]]

Вопрос:
Как мне получить всевозможные значения из этого n-разм…

12
Янв
2021

☕ 33 приема оптимизации JavaScript, которые вы должны знать в 2021 году

Предлагаем вашему вниманию подборку полезных техник и хитростей для оптимизации кода на JavaScript. Она будет интересна не только изучающим язык новичкам, но и опытным программистам.

Хороший разработчик всегда должен учиться чему-то новому и совершенствовать навыки, которые у него уже есть. Поэтому сейчас мы будем учиться писать более чистый и понятный код!

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

В конце статьи приведен список современных возможностей языка, разделенный на версии.

Объявление переменных и присваивание значений

1. Объявление нескольких переменных

Переменные можно объявлять через запятую, при этом не требуется повторно использовать инструкцию let:

        // Длинно
let test1 = 1;
let test2 = 2;

// Коротко
let test1 = 1, test2 = 2;
    

Такой подход особенно удобен при объявлении нескольких переменных без моментального присваивания значений:

        let test1, test2, test3, test4, test5;
    

2. Арифметические операции

Присваивание в JavaScript легко совмещается с арифметическими операторами:

        // Длинно
test1 = test1 + 1;
test2 = test2 - 1;
test3 = test3 * 20;

// Коротко
test1++;
test2--;
test3 *= 20;
    

3. Присваивание значений нескольким переменным

Если требуется присвоить значения сразу нескольким переменным, мы обычно делаем так:

        let test1, test2, test3;
test1 = 1;
test2 = 2;
test3 = 3;
    

Но всю эту логику можно свести в одну строку, если использовать деструктуризацию:

        let [test1, test2, test3] = [1, 2, 3];
    

Синтаксис деструктуризации работает не только с массивами, но и с обычными объектами:

        const data = {
  test1: 1,
  test2: 2,
  test3: 3
};

// Длинно
const test1 = data.test1;
const test2 = data.test2;
const test2 = data.test3;

//shorthand
const { test1, test2, test3 } = data;
    

4. Присваивание со значением по умолчанию

Иногда требуется положить в переменную какое-то значение, предварительно убедившись, что это значение существует и не является falsy (null, undefined, пустая строка, 0).

Для этого можно использовать обычную конструкцию if-else:

        let test2;
if (test1) {
  test2 = test1;
} else {
  test2 = 'default value';
}
    

Можно написать короче.

Взять, например, логический оператор ||. Если в переменной находится truthy-значение, то будет возвращено оно, иначе – дефолтное значение с правой стороны оператора.

        let test 2 = test1 || 'default value';
    

Еще более современный подход – nullish coalescing operator??. Однако он проверяет не на все falsy-значения, а только на null и undefined. В остальном логика такая же, как у оператора ||.

        const test = null ?? 'default value';
console.log(test); // 'default value'

const test1 = 0 ?? 2;
console.log(test1); // 0
    

Условия

5. Автоматическая проверка на truthy и falsy значения

Иногда требуется проверить, есть ли в переменной какое-либо значение. При этом важно учитывать и null, и undefined, и другие falsy-значения (NaN, пустая строка, 0).

        if (test1 !== null || test1 !== undefined || test1 !== '') {
    // logic
}
    

К счастью, нет необходимости проводить все проверки по отдельности, тем более, что при этом легко что-нибудь упустить. Например, 0, который в ряде ситуаций тоже может расцениваться как “пустое” значение.

Можно просто положиться на JavaScript и его динамическую конверсию типов.

        if (test1) {
  // logic
}
    

Оператор if самостоятельно приведет переменную к логическому значению и осуществит проверку.

6. Логические операторы вместо if

В пункте Присваивание с дефолтным значением мы уже видели, как логический оператор (||) может заменить конструкцию if.

Оператор && также способен на многое:

        // Длинно
if (test1) {
 callMethod(); 
} 
// Коротко 
test1 && callMethod();
    

Если test1 является falsy-значением, то до инструкции callMethod() выполнение не дойдет.

7. Тернарный оператор вместо if

Зачастую простые конструкции if-else можно заменить еще более простым тернарным оператором:

        // Длинно
let test: boolean;
if (x > 100) {
    test = true;
} else {
    test = false;
}

// Коротко
let test = (x > 10) ? true : false;

// Еще короче
let test = x > 10;
    

Таким образом можно преобразовать и более сложные условия, даже вложенные:

        let x = 300,
test2 = (x > 100) 
        ? 'greater 100' 
        : (x < 50) 
           ? 'less 50' 
           : 'between 50 and 100';

console.log(test2); // "greater than 100"
    

Важно: чем сложнее условие, тем запутаннее выглядит тернарный оператор и предпочтительнее – стандартная конструкция if-else.

8. Проверка на значение из набора

Если требуется выполнить какие-то действия, когда x равен одному из нескольких значений, первым порывом может быть использование обычных сравнений:

        if (x === 'abc' || x === 'def' || x === 'ghi' || x ==='jkl') {
    //logic
}
    

Но чем больше таких “подходящих” значений, тем сильнее разрастается условие и тем проще сделать ошибку. Проще поместить все эти значения в массив и использовать метод Array.prototype.includes для проверки:

        if (['abc', 'def', 'ghi', 'jkl'].includes(x)) {
   //logic
}
    

Важно: метод includes использует строгое сравнение с учетом типа аргумента.

9. Коллекция вместо switch

Вместо того, чтобы рассматривать каждый случай внутри инструкции switch, можно добавить их все в объект:

        // Длинно
switch (data) {
  case 1:
    test1();
  break;

  case 2:
    test2();
  break;

  case 3:
    test();

  break;
  // ...
}

// Коротко
const collection = {
  1: test1,
  2: test2,
  3: test
};

collection[data] && collection[data]();
    

Циклы

10. Короткий синтаксис for

Всем знакомый старый-добрый цикл for имеет довольно громоздкую структуру:

        for (var i = 0; i < testData.length; i++) {
  // i - индекс элемента
  // доступ к значению элемента i
  var item = testData[i];
}
    

К счастью, в последних версиях языка появилось несколько более удобных альтернатив:

        for (let i in testData) {
  // i - индекс элемента
  // доступ к элементу i
  var item = testData[i];
}

for (let i of testData) {
  // i - значение элемента
}
    

Кроме того, есть замечательный функциональный метод forEach:

        function testData(element, index, array) {
  console.log('test[' + index + '] = ' + element);
}

[11, 24, 32].forEach(testData);
// logs: test[0] = 11, test[1] = 24, test[2] = 32
    

Такой код выглядит очень понятно, но у него есть некоторые ограничения. Например, перебор массива методом forEach нельзя прервать с помощью инструкции break.

Числа

11. Конверсия строки в число

Одиночный оператор сложения (+) неявно приводит тип полученного аргумента к числу.

        // Длинно
let test1 = parseInt('123'); 
let test2 = parseFloat('12.3'); 

// Коротко
let test1 = +'123'; 
let test2 = +'12.3';
    

12. Экспоненциальная запись

Избавиться от большого количества нулей поможет экспоненциальная запись:

        // Длинно
for (var i = 0; i < 10000; i++) { ... }

// Коротко
for (var i = 0; i < 1e4; i++) { ... }
    

13. Возведение в степень

Если вы вдруг до сих пор не знали, то пришло время узнать – в JavaScript есть специальный оператор для возведения в степень:

        // Длинно
Math.pow(2,3); 

// Коротко
2**3 
    

14. Округление

Двойное побитовое отрицание для 32-битных целых чисел дает такой же эффект, как Math.floor (округляет вниз):

        // Длинно
Math.floor(1.9) === 1 // true

// Коротко
~~1.9 === 1 // true
    

Строки

15. Получение символа из строки

Строка – это по сути массив символов, поэтому к каждому из них можно обратиться по индексу:

        let str = 'abc';

// Длинно
str.charAt(2); // c

// Коротко
str[2]; // c
    

16. Повторение строки

Чтобы соединить несколько одинаковых строк в одну, существует несколько подходов. Самый очевидный – и самый громоздкий – использовать цикл:

        let test = ''; 
for(let i = 0; i < 5; i ++) { 
  test += 'test '; 
} 
    

Но есть и более логичный – встроенный метод String.prototype.repeat():

        let test = 'test '.repeat(5);

    

Бонус для любителей нестандартных решений:

        let test = Array(6).join('test ');

    

17. Конкатенация

Составление одной строки из нескольких фрагментов – ужасная головная боль. Нас спасут шаблонные литералы:

        // Длинно
const welcome = 'Hi ' + test1 + ' ' + test2 + '.'

// Коротко
const welcome = `Hi ${test1} ${test2}`;
    

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

        // Длинно
const data = 'abc abc abc abc abc abc\n\t'
    + 'test test,test test test test\n\t'

// Коротко
const data = `abc abc abc abc abc abc
         test test,test test test test`
    

Массивы

18. Наличие элемента

Обычно чтобы проверить, присутствует ли элемент в массиве, мы используем метод indexOf и сравниваем найденный индекс с -1.

        if (arr.indexOf(item) > -1) { 
  // элемент в массиве есть
}

if(arr.indexOf(item) === -1) { 
  // элемента в массиве нет
}
    

Но можно использовать другой подход, без сравнения индексов – побитовый оператор ~.

        if(~arr.indexOf(item)) { 
  // элемент в массиве есть
}

if(!~arr.indexOf(item)) { 
  // элемента в массиве нет
}
    

Оператор ~ возвращает 0 только для значения -1. Для всех других значений будет возвращено число, отличное от нуля, то есть truthy-значение.

Важно: не жертвуйте читаемостью кода в угоду краткости. Используйте побитовые операторы только в том случае, если все члены вашей команды умеют с ними работать.

Не стоит забывать и про удобнейший метод Array.prototype.includes:

        if (arr.includes(item)) { 
  // элемент в массиве есть
}

    

19. Поиск элемента

Метод Array.prototype.find – это удобная функциональная замена простому перебору элементов массива с помощью цикла for:

        // Длинно
function findElementByName(arr, name) {
    for (let i = 0; i < arr.length; ++i) {
        if (arr[i].name === name) {
            return data[i];
        }
    }
}

// Коротко
function findElementByName(arr, name) {
  return arr.find(el => el.name === name);
}

const data = [
  { name: 'John' },
  { name: 'Jane' },
]
findElementByName('Jane'); // { name: 'Jane' }
    

20. Spread-синтаксис

Spread-синтаксис был введен в язык специально для облегчения множества операций со сложными структурами данных.

Например, для конкатенации массивов:

        // Стандартный подход
const data = [1, 2, 3];
const test = [4, 5, 6].concat(data);

// Spread-синтаксис
const data = [1, 2, 3];
const test = [4, 5, 6, ...data];

console.log(test); // [ 4, 5, 6, 1, 2, 3]
    

Или клонирования массива:

        // Стандартный подход
const test1 = [1, 2, 3];
const test2 = test1.slice()

// Spread-синтаксис
const test1 = [1, 2, 3];
const test2 = [...test1];
    

21. Минимальное и максимальное значение

Методы Math.max и Math.min могут принимать любое количество аргументов. Чтобы передать им массив, можно использовать метод Function.prototype.apply:

        const arr = [1,2,3];
Math.max.apply(null, arr); // 3
Math.min.apply(null, arr); // 1
    

А можно воспользоваться деструктуризацией:

        Math.max(…arr); // 3
Math.min(…arr); // 1
    

Объекты

22. Присваивание значений

Если имя свойства совпадает с именем переменной, в которой хранится значение, дублировать его необязательно:

        let test1 = 'a'; 
let test2 = 'b';

// Длинно
let obj = {test1: test1, test2: test2}; 

// Коротко
let obj = {test1, test2};
    

23. Перебор ключей и значений

В современном JavaScript есть сразу 3 метода для перебора объектов: Object.keys(), Object.values() и Object.entries(). Каждый из них возвращает массив – ключей, значений или сразу и того, и другого.

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

        const data = { test1: 'abc', test2: 'cde', test3: 'efg' };

Object.keys(data); // ['test1', 'test2', 'test3'];
Object.values(data); // ['abc', 'cde', 'efg'];
Object.entries(data); // [['test1','abc'],['test2','cde'],['test3','efg']]

    

Функции

24. Параметры по умолчанию

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

        // Длинно
function add(test1, test2) {
  if (test1 === undefined)
    test1 = 1;
  if (test2 === undefined)
    test2 = 2;
  return test1 + test2;
}

// Коротко
function add(test1 = 1, test2 = 2) {
  return test1 + test2;
}


add(5, 10); // 15
add(5); // 7
add(); // 3

add(5, null); // 5


    

Важно: дефолтное значение устанавливается только в том случае, если указанный параметр не передан или равен undefined. На null это не распространяется.

25. Операции в return

В операторе return можно производить разнообразные вычисления, что позволит сэкономить пару строк кода.

        // Длинно
function check(test) {
  if (!test) {
    return 'default value';
  } else {
    return test;
  }
}

// Коротко 
function check(test) {
  return test || 'default value';
}
    

26. Стрелочные функции

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

        // Длинно
[1, 2, 3].map(function(i) { 
  return i * 2;
});

// Коротко
[1, 2, 3].map(i => i * 2);
    

Стрелочные функции позволяют возвращать значение неявно, без использования оператора return:

        // Длинно
function calculate(diameter) {
  return Math.PI * diameter
}

// Коротко
calculate = diameter => Math.PI * diameter;
    

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

***

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

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

***

Современные возможности JavaScript

ES2021/ES12

ES2020/ES11

ES2019/ES10

ES2018/ES9

ES2017/ES8

ES2016/ES7

10
Янв
2021

Какую выбрать технологию для интерактива на сайте, чтобы не сильно углубляться во frontend?

Хочу создать свой форум (на подобие Habr, но не сильно замороченный), но возникли трудности.
Технологии, которые я выбрал для разработки:
backend:

Python/Django
MySQL

frontend:

База: html/css
JS – для интерактива

И прочие
Так вот В чём…

05
Янв
2021

Что представляет собой понятие сервер в веб – разработке?

Пытаюсь понять и найти информацию что подразумевается под понятием "сервер" или "EBS" в веб – разработке, если не путаю, то это еще называют back-end.
Т.е некоторые элементы созданные на html, с стилем заданным на css …

14
Дек
2020

🕸 Обучение веб-разработке: сайты, блоги и комьюнити

Посвященные веб-разработке ресурсы – огромный стог сена, в котором вам нужно найти маленькую иголку. Обойтись без них нельзя: сайты, каналы, блоги и сообщества помогают в обучении и поиске работы. Рассказываем о самых интересных источниках.

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

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

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

Telegram-каналы

Frontender’s notes – Фронтендер собирает материалы, которые показались ему полезными: статьи, видео и подкасты. Большинство ресурсов на русском. Материалы не только технические, но и, например, посвященные карьере.

Вместе с коллегами он также админит несколько чатов (есть ссылки в описании к каналу) по JS, CSS, фронтенду в целом.

Frontend Info – ссылки на заинтересовавшие автора статьи англоязычного веба.

TelegaDevIT – много полезных инструментов, иногда мемы.

JavaScript – релизы новых технологий из мира JS, ссылки на англоязычные статьи.

Веб-стандарты – новости фронтенда, инструменты, туториалы. Есть прилагающийся чат. А еще – подкасты на youtube, в которых админы канала обсуждают новости приглашенными гостями.

Smart Dev – отбор англоязычных материалов с короткими комментариями автора, переводы статей. В отличие от предыдущего ресурса, спектр материалов здесь шире: веб-разработка в целом и дизайн.

Defront – ведет канал бывший разработчик Яндекса. Здесь публикуются подробные комментарии с мнением автора о найденных материалах. В описании можно найти рекомендации еще одного канала – Вебня.

Сайты

CSS-liveориентированный на фронтенд русскоязычный ресурс. Новости, практические кейсы, разбор теоретических моментов, переводы англоязычных материалов, подборки красивых эффектов и интересных идей. Можно обсуждать заинтересовавшие вас темы в комментариях.

Josh W. Comeau – блог ведет преподаватель CSS. Пишет он про React, Next.js, анимацию, Gatsby, карьеру. Здесь же можно подсмотреть интересные веб-решения не только в его статьях, подборках и сниппетах, но и на самом сайте (кнопки со звуком, ночной режим и т. д.).

MDN Web Docs – в большей степени образовательная платформа. Она будет полезна не только начинающим: здесь регулярно мелькают новые технологии и инструменты. Чтобы получать эти блага, нужно зарегистрироваться. К тому же на сайте есть открытое сообщество, где можно делиться знаниями, помогая коллегам совершенствовать контент.

Frontend Front – комьюнити, где можно размещать свои проекты и статьи, а также задавать вопросы и голосовать за чужие материалы. Посты, которые набрали больше всего голосов, высылаются по подписчикам по почте.

Scotch.io – туториалы, новости и курсы. Можно подписаться на ежемесячные челленджи по разработке. Задания вы получаете на почту, а потом и решения для самопроверки. Смотрите предыдущие челленджи и их разборы. Во время решения задач и прочтения туториалов на сайте доступен словарь JavaScript. Есть одноименный чат в Slack, но он не очень оживленный.


Личные блоги веб-разработчиков

Firt dev – блог независимого разработчика мобильных и веб-приложений из Буэнос-Айреса, Максимильяно Фиртмана автора 12 книг о программировании и множества технических статей, ментора и преподавателя. Материалы делятся на короткие заметки (notes) и лонгриды (articles). Есть раздел learn, где собраны курсы, семинары, книги и выступления автора.

John Papa – Developer Advocate в Microsoft, когда-то работал в Disney. Даем ссылку на его твиттер, потому что он гораздо более оживленный, но сайт со старыми материалами тоже можно посмотреть.

Rebecca Murphey – главный инженер в Stripe, работала в Indeed. Она пишет о фронтенде и не технических темах, связанных с карьерой и работой. Ее твиттер.

Hugo Giraudel – ведущий инженер по фронтенду, который специализируется на доступности и безопасности рабочих мест. В его блоге кроме статей вы найдете сниппеты.

Angus Croll – JS-разработчик из Netflix написал книгу «Если бы Хемингуэй написал JavaScript». Доступен также блог на медиуме и сайт.

Jen Simmons – дизайнер и разработчик в Mozilla, член рабочей группы CSS. Одно из ее основных направлений – CSS Grid. На сайте не так много текста, но можно словить вдохновение. Всякие фишки стоит смотреть на ютуб-канале автора.

Chris Coyier – один из создателей Codepen ведет подкаст ShopTalk о фронтенде, веб-дизайне и UX. У него очень популярный Твиттер.

André Staltz – основатель фреймворка cycle.js сделал значительный вклад в ReactiveX. Он также создал бесплатную социальную сеть Manyverse, где ваши данные не нужно загружать на сервера компании. В блоге автор пишет о JavaScript, интерфейсах, реактивном программировании, React Native и одноранговых сетях. Последний пост в блоге за 2019 год, более свежее мнение автора можно читать в Твиттере.

Meyerweb – эксперт по веб-стандартам (HTMLи CSS). Он написал множество популярных книг по CSS и не только, а также является создателем ряда инструментов и организатором мероприятий для дизайнеров и фронтендеров – An Event Apart.

Swizec – блог о JavaScript преподавателя Swizec Teller с опытом разработки в 13 лет. Автор рассказывает не только о технических нюансах, но и о софт–скилах, а также о карьере. Кроме сайта Swizec он активно ведет свой Твиттер и написал несколько книг (есть на сайте).

Addy Osmani – главный инженер в Google Chrome, специализирующийся на ускорении веба. Его команда работает над такими инструментами, как Lighthouse, PageSpeed Insights, Chrome User Experience Report.

Infrequently Noted – блог Алекса Рассела, который тоже из Chrome, но возглавляет работу с веб-стандартами. Один из его проектов – Blink.

2ality – блог ведет разработчик с опытом в 25 лет, преподаватель, писатель. Основное направление – JavaScript. Кроме личного блога, у него есть ресурс ESnextNews с новостям о JS и еженедельной рассылкой.

Чаты и форумы

Огромное количество локальных русскоязычных чатов и сообществ вы найдете в этой подборке на GitHub. Там представлены Россия, Беларусь, Украина, Казахстан и Молдова. Такие комьюнити особенно полезны, потому что они дают участникам возможность знакомиться и общаться, помогая друг другу на местности.

Кстати, на сайте можно добавлять чаты через pull request, чтобы найти единомышленников из своих регионов, которые не представлены в списке.

DEV – здесь любой может опубликовать свой материал и прокомментировать чужие. Также на форуме собираются видео и подкасты. Еще есть раздел с объявлениями: вакансии, поиск и предложения менторства, курсы, мероприятия, приглашения в другие сообщества разработчиков. По тегам слева выбирается интересующая читателя тематика.

Hashnode – местами похож на предыдущий ресурс, но есть интересная опция: можно создавать свои Q&A-сессии или задавать вопросы запустившим сессию экспертам. Например, расспросить о чем-нибудь разработчиков Google и Amazon, а также разных фаундеров из мира программирования. Можно искать интересующие топики по тегам. Комментарии и посты при необходимости публикуются анонимно.

The Odin Project – образовательная платформа с чатом в Дискорде. Основные направления обучения – JavaScript и Ruby. Еще у них есть блог на медиуме.

SitePoint – достаточно активный форум для веб-разработчиков и веб-дизайнеров. Ищите обсуждения по категориям: например, только PHP.

Product Hunt – здесь вы найдете последние веб- (и не только) проекты. Можно комментировать их, задавать вопросы создателю, подсматривать интересные решения.

WebDeveloper – минималистичный форум по веб-разработке. В отличие от некоторых других, он разделен на секции: часто задаваемые вопросы, клиент сайта, сервер сайта, управление сайтом.

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

В целом, на Reddit есть и более узкие сабреддиты, вроде: Bootstrap, JavaScript и т. д.

Заключение

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

***

Если вы только осваиваете профессию веб-разработчика и не готовы тратить слишком много времени на самообучение, стоит обратить внимание на курс по веб-разработке от Geek Brains и Mail.ru. Начав с основ, вы получите необходимые для начала карьеры знания. Актуальная программа состоит из 2 – 3 вебинаров в неделю и 2 месяцев стажировки. Под руководством опытных преподавателей студенты наработают необходимую для дальнейшего развития базу и получат помощь в трудоустройстве.

12
Дек
2020

🛠 Хватит использовать REST для API!

Технологии прогрессируют быстро и даже для лучших из них появляются альтернативы. Разбираем преимущества и недостатки REST и GraphQL, чтобы выбрать лучший вариант.

REST – широко распространенная технология передачи данных по протоколу HTTP, которая до недавнего времени была де-факто стандартом веб-разработки. Однако развитие интернета не стоит на месте и у старичка появился конкурент – GraphQL. В этой статье мы рассмотрим преимущества и ограничения обеих технологий: попробуем решить, какую же из них выбрать.

Что такое REST?

REST (Representational State Transfer) – это стиль проектирования API, буквально обозначающий передачу состояния представления. Веб-службы REST используют для передачи и получения информации предопределенный набор операций, включая GET, POST, PUT и DELETE, и не сохраняют состояние приложения.

Основная идея REST очень проста – на URL-адрес ресурса отправляется запрос определенного типа и формата, на который приходит ответ с нужными данными (обычно в формате JSON).

Преимущества REST

  1. Масштабируемость. Так как архитектура REST разделяет клиент и сервер, ее легко расширять, что позволяет масштабировать приложение без особых проблем.
  2. Гибкость. Кроме того, эта архитектура весьма гибкая и дает возможность обрабатывать различные типы запросов и форматы данных.

Ограничения REST

  1. Чрезмерная выборка. Зачастую конечная точка API предоставляет на запрос лишнюю информацию, которая не требуется клиенту для совершения действий. Например, вы хотите получить только имя пользователя, но метод сообщает вам еще его возраст, телефон и электронную почту.
  2. Недостаточная выборка. Возможна и обратная ситуация, когда клиенту приходится делать несколько запросов, чтобы получить всю информацию, которая ему нужна. Например, из одной конечной точки API вы получаете личные данные пользователя, а из другой – информацию о сделанных им заказах.

Что такое GraphQL?

GraphQL использует другой стиль проектирования API – все рассматривается как граф, в котором данные взаимосвязаны. Это означает, что запрос можно настроить таким образом, чтобы из одной конечной точки получить всю необходимую информацию – и ничего больше. Таким образом можно даже объединять в одном запросе разные сущности.

Преимущества GraphQL

  1. Все нужное и ничего лишнего. В GraphQL вы получаете только то, что просите, и больше ничего.
  2. Быстрая разработка на клиенте. Если нужно изменить что-то в данных, достаточно лишь немного подправить запрос. Это позволяет быстрее развивать продукт. Клиентскую и серверную разработку можно вести независимо друг от друга, при условии, что обе команды знают структуру данных.

Ограничения GraphQL

  1. Сложность. Для небольших простых приложений настройка таких запросов может показаться слишком сложной и ненужной. В этой ситуации легко можно обойтись классическим REST-подходом.
  2. Нет кеширования. GraphQL использует всего одну конечную точку, что не позволяет следовать спецификации HTTP-кеширования. Это очень важно, так как кеширование уменьшает объем трафика.

Простой пример для сравнения

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

REST-реализация

Если мы используем архитектуру REST, то придется сделать несколько запросов (2-3):

  1. /user/<id> – для получения сведений о пользователе.
  2. /user/<id>/posts – для получения списка сообщений, опубликованных этим пользователем.
  3. /user/<id>/followers – для получения списка подписчиков.

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

GraphQL-реализация

Здесь и проявляется вся мощь GraphQL.

В запросе мы можем указать точный набор нужных данных, например, вот так:

        query {
  User(id: '123') {
    name
    posts {
      title
    }
    followers {
      name
    }
  }
}
    

И в ответ получим именно то, чего ожидаем. Очень просто и чисто.

GraphQL vs REST

Пора подвести итог противостояния. Для этого сравним оба стиля по основным параметрам:

1. Получение данных

У REST есть проблемы с комплектацией: получаемые из конечной точки данные часто бывают избыточными или неполными. У GraphQL этого недостатка нет.

2. Структура ответа

В REST-архитектуре структуру ответа определяет сервер, а в GraphQL – клиентский код.

3. Автоматическое кэширование

REST использует кэширование ответов по умолчанию, в то время как GraphQL не имеет системы автоматического кэширования. Однако существуют различные клиенты GraphQL (Apollo, Relay), которые предоставляют эту возможность.

4. Обработка ошибок

В REST обработка ошибок намного проще. GraphQL обычно возвращает статус 200 OK даже с ошибкой, но при использовании специальных клиентов эта проблема легко решается.

***

Преимущества GraphQL перед REST очевидны, однако это не всегда лучший вариант для вашего приложения. Выбирая технологию, учитывайте особенности проекта: сложность, размер, потенциальное расширение и организацию процесса разработки.

08
Дек
2020

cmd.run in lifecycle hooks strapi

Code below working on development mode, but in production, it throws premission error
CMS: Strapi.io

‘use strict’;

/**
* Read the documentation (https://strapi.io/documentation/v3.x/concepts/models.html#lifecycle-hooks)
* to customize …

19
Ноя
2020

Сессия в Node.js быстро сбрасывается

Сессия устанавливается после авторизации. Если попереключаться по ссылкам внутри сайта, все работает нормально. Стоит оставить вкладку неактивной, через 5-10 минут сессия сбрасывается.
Код конфигурации сессии:
const session = require(‘expr…