JS - копирование объекта:
- Для копирования объектов есть функция assign. Как она работает:
- функция принадлежит объекту Oblect, поэтому вызывается через Object.assign().
- Она принимает параметры: target - единственный, source - множество, где:
1. target - объект, который возвратит функция.
2. source - объект, из которого копируются ключи-значения.
Пример с клонированием объекта:
let obj = { key: value }
let clone = Object.assign({}, obj)
Здесь функция копирует в пустой объект содержимое obj и присваивает пустой объект переменной clone. Source может быть и объект, определенный прямо в функции.
ВАЖНО: порядок указания sources задает приоритет перезаписи свойств при клонировании. Например в коде:
Object.assign({}, src1, src2)
src1 будет иметь больший приоритет, и если в src2 встретится свойство, аналогичное содержащемуся в src1, оно будет перезаписано свойством из src1.
Эта тема важна для понимания иммутабельности в React.
#JS #React
- Для копирования объектов есть функция assign. Как она работает:
- функция принадлежит объекту Oblect, поэтому вызывается через Object.assign().
- Она принимает параметры: target - единственный, source - множество, где:
1. target - объект, который возвратит функция.
2. source - объект, из которого копируются ключи-значения.
Пример с клонированием объекта:
let obj = { key: value }
let clone = Object.assign({}, obj)
Здесь функция копирует в пустой объект содержимое obj и присваивает пустой объект переменной clone. Source может быть и объект, определенный прямо в функции.
ВАЖНО: порядок указания sources задает приоритет перезаписи свойств при клонировании. Например в коде:
Object.assign({}, src1, src2)
src1 будет иметь больший приоритет, и если в src2 встретится свойство, аналогичное содержащемуся в src1, оно будет перезаписано свойством из src1.
Эта тема важна для понимания иммутабельности в React.
#JS #React
JS: spread-оператор для массивов
- Как выглядит spread-оператор:
let clone = [...array];
Внешне он похож на rest-оператор.
- Что он делает?
Раскладывает массив на отдельные элементы.
- Какие задачи решает?
1. Передача массива функции. В ES5 для этого требовался метод apply либо другие, более сложные кастомные функции. Spread упрощает задачу:
const test = (...array) => array.map((i) => i * 2);
console.log(test(...[5, 4, 3])) // 10, 8, 6
2. Клонирование массива (свойств, но не ссылки на оригинал):
const array = [a, b, c];
const clone = [...array]; // [a, b, c]
3. Преобразование коллекций в массивы:
const links = [...document.querySelectorAll('a')];
#JS
- Как выглядит spread-оператор:
let clone = [...array];
Внешне он похож на rest-оператор.
- Что он делает?
Раскладывает массив на отдельные элементы.
- Какие задачи решает?
1. Передача массива функции. В ES5 для этого требовался метод apply либо другие, более сложные кастомные функции. Spread упрощает задачу:
const test = (...array) => array.map((i) => i * 2);
console.log(test(...[5, 4, 3])) // 10, 8, 6
2. Клонирование массива (свойств, но не ссылки на оригинал):
const array = [a, b, c];
const clone = [...array]; // [a, b, c]
3. Преобразование коллекций в массивы:
const links = [...document.querySelectorAll('a')];
#JS
JS - деструктуризация объектов:
Рассмотрим сложный случай:
const { hello, bye, space: { full = 'Vacuum' } = {} } = obj;
Что здесь происходит:
1. Объявляется константа.
2. Ей присваевается объект obj;
3. В фигурных скобках создаются константы с именами свойств этого объекта - hello, bye, space, full.
4. Константа space содержит значение по-умолчанию:
1. Если в объекте нет значения space, оно задаётся как новый пустой объект;
2. Если в новом объекте нет значения full (а его там нет), создается константа full со значением по-умолчанию "Vacuum". Если в объект добавить такое свойство, значение по-умолчанию будет проигнорировано.
Боевое применение деструктуризации (и значений по-умолчанию):
Когда функции или модулю передается объект опций, можно деструктурировать его и одновременно присвоить значения по-умолчанию прямо на входе:
const handlerFunction = ({login = 'admin', port = '860'} = {}) => { // some code }
Заметим, что объекту опций по-умолчанию присвоен пустой объект: так обходится ошибка при вызове функций полностью без аргументов.
Деструктуризация помогает в создании копий объектов или включении их в новый, не используя Object.assign:
const clone = { ...src1, ...src2 }
#JS
Рассмотрим сложный случай:
const { hello, bye, space: { full = 'Vacuum' } = {} } = obj;
Что здесь происходит:
1. Объявляется константа.
2. Ей присваевается объект obj;
3. В фигурных скобках создаются константы с именами свойств этого объекта - hello, bye, space, full.
4. Константа space содержит значение по-умолчанию:
1. Если в объекте нет значения space, оно задаётся как новый пустой объект;
2. Если в новом объекте нет значения full (а его там нет), создается константа full со значением по-умолчанию "Vacuum". Если в объект добавить такое свойство, значение по-умолчанию будет проигнорировано.
Боевое применение деструктуризации (и значений по-умолчанию):
Когда функции или модулю передается объект опций, можно деструктурировать его и одновременно присвоить значения по-умолчанию прямо на входе:
const handlerFunction = ({login = 'admin', port = '860'} = {}) => { // some code }
Заметим, что объекту опций по-умолчанию присвоен пустой объект: так обходится ошибка при вызове функций полностью без аргументов.
Деструктуризация помогает в создании копий объектов или включении их в новый, не используя Object.assign:
const clone = { ...src1, ...src2 }
#JS
JS - деструктуризация массивов:
Из особенностей деструктуризации массивов можно отметить возможность пропуска элемента:
const arr = ['hello', 'world', 'space', 'name'];
const [,one, ...two] = arr;
// one = world, two = ['space', 'name']
Такая деструктуризация поддерживает и значения по-умолчанию.
#JS
Из особенностей деструктуризации массивов можно отметить возможность пропуска элемента:
const arr = ['hello', 'world', 'space', 'name'];
const [,one, ...two] = arr;
// one = world, two = ['space', 'name']
Такая деструктуризация поддерживает и значения по-умолчанию.
#JS
JS - прототипы:
Есть несколько способов относительно явно присвоить прототип. Я ограничусь примерами кода:
1. Object.setPrototypeOf(newObject, prototype) - не рекомендуется из-за проблем с производительностью.
2. let obj = Object.create(prototype) - проблема в отсутствии свойств. Решается созданием обертки.
3. Классика (самый удобный способ):
function Obj() {};
Obj.prototype.method = function(){};
4. obj.__proto__ = prototype. Не рекомендуется, как и setPrototypeOf.
#JS
Есть несколько способов относительно явно присвоить прототип. Я ограничусь примерами кода:
1. Object.setPrototypeOf(newObject, prototype) - не рекомендуется из-за проблем с производительностью.
2. let obj = Object.create(prototype) - проблема в отсутствии свойств. Решается созданием обертки.
3. Классика (самый удобный способ):
function Obj() {};
Obj.prototype.method = function(){};
4. obj.__proto__ = prototype. Не рекомендуется, как и setPrototypeOf.
#JS
JS - замечания о классах:
- появились статические свойства, привязанные к классу. Задаются они ключевым словом static - неожиданно, правда?
- методы, заданные в конструкторе, привязываются к объекту класса, их this ссылается на этот объект. Поэтому не нужно такие методы привязывать:
this.method.bind(this)
#JS
- появились статические свойства, привязанные к классу. Задаются они ключевым словом static - неожиданно, правда?
- методы, заданные в конструкторе, привязываются к объекту класса, их this ссылается на этот объект. Поэтому не нужно такие методы привязывать:
this.method.bind(this)
#JS
JS - о rest-операторе:
Оператор rest при деструктуризации собирает не последние оставшиеся свойства, а все, кроме тех, с которыми деструктуризация была выполнена явно:
const { id, ...rest } = targetObject;
Здесь id будет иметь значение id из targetObject, а ...rest - соберет все остальные, как перед, так и после id.
Таким образом можно без труда разделить объект на нужные части и передавать в разные части приложения только их, а не весь объект.
#JS
Оператор rest при деструктуризации собирает не последние оставшиеся свойства, а все, кроме тех, с которыми деструктуризация была выполнена явно:
const { id, ...rest } = targetObject;
Здесь id будет иметь значение id из targetObject, а ...rest - соберет все остальные, как перед, так и после id.
Таким образом можно без труда разделить объект на нужные части и передавать в разные части приложения только их, а не весь объект.
#JS
React - привязка методов
В классах Реакта можно заметить биндинг методов-обработчиков событий:
this.method = this.method.bind(this)
Биндинг внутри класса может показаться нелогичным. Виновник потребности в нем - потеря контекста this, когда метод присваивается другой переменной:
<element onClick=this.method>
Биндинг связывает this с контекстом класса, и контекст уже не теряется.
Есть и другие способы привязки this в классе. Подробнее:
https://getinstance.info/articles/react/react-and-es6-part3/
#React #JS
В классах Реакта можно заметить биндинг методов-обработчиков событий:
this.method = this.method.bind(this)
Биндинг внутри класса может показаться нелогичным. Виновник потребности в нем - потеря контекста this, когда метод присваивается другой переменной:
<element onClick=this.method>
Биндинг связывает this с контекстом класса, и контекст уже не теряется.
Есть и другие способы привязки this в классе. Подробнее:
https://getinstance.info/articles/react/react-and-es6-part3/
#React #JS
getinstance.info
React и ES6 - Часть 3, Биндинг методов в классах React (включая ES7)
Статьи о фронтенд-разработке: HTML, CSS, JavaScript, фреймворки и инструменты фронтендера, уроки и переводы зарубежных статей по веб-разработке
Тонкости импорта
В нативных модулях ES6 параметр import принимает строкой путь к модулю:
import React from 'react'
Этот путь может быть нескольких видов. Относительный и абсолютный используется по-умолчанию для кастомных модулей:
'./relativePath'
'/absolute/Path'/
Есть и третий вариант - им начинается заметка.
Обычный модуль так подключить нельзя, даже если он расположен в той же папке, что и импортирующий.
Есть два предположения, почему так происходит:
1. Такой способ импорта допустим для встроенных модулей и библиотек со специфическими настройками;
2. Такой способ специфичен для Webpack.
А вы как думаете?
#JS #React
В нативных модулях ES6 параметр import принимает строкой путь к модулю:
import React from 'react'
Этот путь может быть нескольких видов. Относительный и абсолютный используется по-умолчанию для кастомных модулей:
'./relativePath'
'/absolute/Path'/
Есть и третий вариант - им начинается заметка.
Обычный модуль так подключить нельзя, даже если он расположен в той же папке, что и импортирующий.
Есть два предположения, почему так происходит:
1. Такой способ импорта допустим для встроенных модулей и библиотек со специфическими настройками;
2. Такой способ специфичен для Webpack.
А вы как думаете?
#JS #React
Спасибо всем, кто участвовал в опросе.
Верный вариант - специфика Webpack.
Дело в том, что приложения Реакт создаются для бразузера. Директива import для именованных импортов - как в случае импорта Реакта - не поддерживается большинством браузеров, поэтому Реакт использует для сборки Webpack. Который, в свою очередь, ищет пути к модулям, импортированным так, в папке node_modules. Неочевидное поведение, которое полезно держать в голове.
#JS #React #Webpack
Верный вариант - специфика Webpack.
Дело в том, что приложения Реакт создаются для бразузера. Директива import для именованных импортов - как в случае импорта Реакта - не поддерживается большинством браузеров, поэтому Реакт использует для сборки Webpack. Который, в свою очередь, ищет пути к модулям, импортированным так, в папке node_modules. Неочевидное поведение, которое полезно держать в голове.
#JS #React #Webpack
jQuery - лучшие практики:
- Для подключения:
1. Всегда оставлять возможность загрузки локальной копии:
window.jQuery || document.write(путь к CDN)
2. В пути к CDN опускать протокол:
//...путь
- Для переменных:
1. Желательно сохранять jQuery-объекты в переменные, таким образом кэшируя их.
2. Созданные для этого переменные желательно именовать с префиксом $: const $selectors = $(...)
- Для селекторов:
1. Предпочтительно использовать ID-селекторы.
2. Для поиска дочерних вложенных элементов предпочтительнее метод .find(), чем указание вложенности в селекторе:
$("#products").find("div.id");
3. Вообще конкретизировать область поиска селекторов:
$('.class', '#class-container');
4. Не смешивать ID с другими селекторами (теряется оптимизация поиска).
- Обработка DOM:
1. Если элемент нужно обработать, его нужно извлечь из DOM с сохранением информации о нем. Для этого используется .detach():
let $myList = $("...").detach();
//... действия по обработке $myList
$myList.appendTo("#list-container");
2. Если элемента может не быть на странице, нужно выполнять проверку его присутствия, прежде чем запускать логику взаимодействия.
#JS #jQuery #best_practices
- Для подключения:
1. Всегда оставлять возможность загрузки локальной копии:
window.jQuery || document.write(путь к CDN)
2. В пути к CDN опускать протокол:
//...путь
- Для переменных:
1. Желательно сохранять jQuery-объекты в переменные, таким образом кэшируя их.
2. Созданные для этого переменные желательно именовать с префиксом $: const $selectors = $(...)
- Для селекторов:
1. Предпочтительно использовать ID-селекторы.
2. Для поиска дочерних вложенных элементов предпочтительнее метод .find(), чем указание вложенности в селекторе:
$("#products").find("div.id");
3. Вообще конкретизировать область поиска селекторов:
$('.class', '#class-container');
4. Не смешивать ID с другими селекторами (теряется оптимизация поиска).
- Обработка DOM:
1. Если элемент нужно обработать, его нужно извлечь из DOM с сохранением информации о нем. Для этого используется .detach():
let $myList = $("...").detach();
//... действия по обработке $myList
$myList.appendTo("#list-container");
2. Если элемента может не быть на странице, нужно выполнять проверку его присутствия, прежде чем запускать логику взаимодействия.
#JS #jQuery #best_practices
jQuery - лучшие практики, часть 2:
- События:
1. Использовать только один обработчик события document.ready, а не распихивать код по нескольким.
2. Описывать функции обработки событий вне обработчика, передавая ему только имя функции. Выгода - читабельность, легкость отладки.
3. Используя jQuery, стоит всегда назначать события через него - без инлайн-кода. Выгода - консистентность.
- Анимация:
1. Лучше предустановленные значения скорости анимации, чем кастомные.
- Плагины:
1. Хорошо задокументированные популярные плагины предпочтительнее - сообщество следит за багами и уязвимостями.
- Чейнинг:
1. Чейнинг методов предпочтительнее создания новых переменных или селекторов. Для легкости чтения звенья лучше разносить по строкам. В длинных цепочках можно кэшировать промежуточные объекты.
- Прочее:
1. Для передачи нескольких однотипных параметров лучше не вызывать метод несколько раз, а передать параметры литералом объекта:
$myLink.attr({
href: "#",
title: "my link",
rel: "external"
});
2. Не стоит писать CSS прямо в jQuery, вместо этого лучше определить правило в таблице стилей и передавать его элементу.
Warning! Часть инфы может быть неактуальной для новых версий jQuery.
#JS #jQuery #best_practices
- События:
1. Использовать только один обработчик события document.ready, а не распихивать код по нескольким.
2. Описывать функции обработки событий вне обработчика, передавая ему только имя функции. Выгода - читабельность, легкость отладки.
3. Используя jQuery, стоит всегда назначать события через него - без инлайн-кода. Выгода - консистентность.
- Анимация:
1. Лучше предустановленные значения скорости анимации, чем кастомные.
- Плагины:
1. Хорошо задокументированные популярные плагины предпочтительнее - сообщество следит за багами и уязвимостями.
- Чейнинг:
1. Чейнинг методов предпочтительнее создания новых переменных или селекторов. Для легкости чтения звенья лучше разносить по строкам. В длинных цепочках можно кэшировать промежуточные объекты.
- Прочее:
1. Для передачи нескольких однотипных параметров лучше не вызывать метод несколько раз, а передать параметры литералом объекта:
$myLink.attr({
href: "#",
title: "my link",
rel: "external"
});
2. Не стоит писать CSS прямо в jQuery, вместо этого лучше определить правило в таблице стилей и передавать его элементу.
Warning! Часть инфы может быть неактуальной для новых версий jQuery.
#JS #jQuery #best_practices
Полезные практики в React:
- Сократить код обращения к this.state можно, пользуясь деструктуризацией:
const { firstState, secondState } = this.state
- Вынести за пределы компонента логику коллебка можно, используя функцию высшего порядка:
const handler = itemToFind => item => item.title.includes(itemTiFind)
Здесь функция handler возвращает функцию, которая передается, например, в map и используется для фильтрации.
#React #JS
- Сократить код обращения к this.state можно, пользуясь деструктуризацией:
const { firstState, secondState } = this.state
- Вынести за пределы компонента логику коллебка можно, используя функцию высшего порядка:
const handler = itemToFind => item => item.title.includes(itemTiFind)
Здесь функция handler возвращает функцию, которая передается, например, в map и используется для фильтрации.
#React #JS