Comments 16
Сначала я удивился. Я недавно видел что-то похожее у Мурыча. Подумал, что эта статья - плагиат. Но в конце статьи заметил ссылку.
Вообще, я давно хотел написать статью на эту тему, но всё время откладывал на потом. Однако не так давно увидел видео/стрим Мурыча, и он меня вдохновил осветить эту тему, так как он очень детально показал, что и как. И я взял его примеры за основу. Благодаря этому статья получилась довольно обширной, соответственно, я указал автора, так как многое брал оттуда как основу повествования
Удали из статьи повторяющиеся абзацы (например аж два раза тебя в конце Мурыч вдохновил), а также nbsp после const из примера с кодом.
А есть практический смысл присваивать массив там, где предполагается об'ект? Взяли какой то высосанный из пальца пример и доказываете, что то не эффективно. Возьмите нормальный жизненный пример деструктуризации. Слева { }, справа объект и покажите где там не эффективно.
1) Много кода, где людьми возвращается что угодно, как со смыслом, так и бездумно, из разных функций/методов и т. д.
2) Суть статьи была показать разницу: хоть интуитивно и кажется понятным, что оно работает одинаково на самом деле внутри это работает по-разному.
3) А кто говорил, что Object Assignment Pattern это неэффективно?
4) Насчет возвращаемого значения (массив вместо объекта), вот вам банальный до ужаса пример: React хук useState.
Вообще, если честно, я не понял комментария. Суть повествования была в том чтобы привнести ясность, чтобы разработчик понимал вес того, что он пишет
Интересно конечно разбираться поглубже в языке, спасибо за статью. Только вот насколько это реально применимо? Вы упомянули про реакт, я как раз сейчас на него перехожу, поэтому тема очень актуальна. Сколько мы сэкономим если будем использовать useState через индексы и насколько сильно будет ругаться команда, когда такое увидит? Вопросы конечно риторические. Но поразмышлять и правда интересно, как часто мы используем что-то не зная, как это работает под капотом
Спасибо в первую очередь за интерес и вопрос!
А почему это не должно быть применимо? Вопрос уже в том, хотите ли вы заботиться о производительности или нет. Если все делают что-то, это же не означает, что это верно, тем более в современном IT
Так что здесь зависит от команды. Если вы расскажете подробно, почему, и приведете примеры, то команда выслушает вас и, возможно, изменится в лучшую сторону. Если нет, то работа на то и работа, чтобы мы писали там, как хочет команда. Но никто не запрещает писать потом для себя или для своих проектов так, как нужно
Насчет того, действительно ли это увеличит производительность? Это зависит от проекта: если он маленький, то сильного эффекта вы не увидите. Но тут, даже логически подумать, итератор - это довольно сложная для V8 штука, которая сложно оптимизируется. Поэтому array assignment pattern по-любому медленнее. А теперь сложите все useState в том самом React вместе (до кучи) в каждом файле и подумайте, действительно ли что-то меняется или нет
Спасибо за статью!
Правильно ли я понимаю в контексте useState, что условный
const [number, setNumber] = useState(0);
работает медленнее, чем
const someNumber = useState(0);
const number = someNumber[0];
const setNumber = someNumber[1];
Да, правильно. Но не совсем по той причине, что описаны в статье. Автор пишет:
основанное на наших собственных домыслах о работе JS
Но в итоге статья основывается на тех же домыслах. Давайте на примере вашего хука, посмотрим где реально проблема. Возьмем хук (я написал псевдо хук, но оригинал в реакте именно так работает):
function useState() {
// ...
return [get, set];
}И то как он используется:
function Component() {
const [state, setState] = useState()
}Прочитав статью можно сделать вывод, что проблема здесь в переборе итератора, или как автор пишет:
for (let index=0; index<arr.length; index++) {
if(index===3) {
value = arr[index];
}
}Что в общих чертах напоминает работу механизма Array Assignment Pattern (перебор итератора).
Но это заблуждение и подмена смысла, проблема не в самом переборе итератора, а в том, что это каждый раз новый итератор. Чтобы это понять, нужно еще раз посмотреть, что именно происходит когда мы используем useState (в обратном порядке):
const [state, setState] = useState();Аллоцирем память под новый массив, который каждый раз попадает в случайную область памяти.
Вызываем функцию
useState, которая возвращая нам массив – делает тоже самое – аллоцирует память под новый массив на каждом вызове, а массив попадает в случайную область памяти:
return [get, set] // !!!Из этого следует, что JIT вообще никак не может заинлайнить или оптимизировать этот код, он непредсказуем и память фрагментирована. В этом суть проблемы, а не в самом переборе итератора.
Спасибо за разъяснения! Вот и я подумал, что useState не совсем правильный пример, но ваш ответ помог лучше понять что творится под капотом.
Поставил бы вам плюсик, но кто-то подпортил мне карму :)
Спасибо, в первую очередь, за комментарий и желание разобраться глубже!
Ну, не совсем так пример был больше для привлечения внимания, так как это очень известная конструкция.
Но суть проблемы это не отменяет, потому что создание итератора каждый раз и который плохо оптимизируется, и при этом человек даже не догадывается об этом - в этом по сути, и был главный посыл всего
Да, вы правы, это как раз каждый раз новый итератор.
1)Суть повествования была в том, чтобы показать, что это итератор, поскольку многие даже не догадываются об этом.
2)Второй пункт - показать что из-за того, что это итератор, и по своей природе плохо оптимизируется, он хуже по производительности чем обжект ассайн паттерн. То есть в случае если мы знаем ключ(индекс) то лучше использовать связывание по ключу
Что касается useState, это просто самый известный пример, который многие увидят и которым заинтересуются. Здесь больше был расчёт на это
Задумывался об этом. Чаще когда нужно получить элемент массива, использую arr.at(-1) допустим.
И касательно изображения картинки примера на V8, смотрю с телефона. У вас написано, что паттерн присваивания массивов справа. не слева разве?
Убивает ли ваша деструктуризация производительность?