Когда я начал изучать JavaScript, то первым делом составил список приемов, которые помогали мне экономить время. Я подсмотрел их у других программистов, на разных сайтах и в мануалах.
В этой статье я покажу 12 отличных способов улучшить и ускорить свой JavaScript-код. В большинстве случаев они универсальны.
Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».
Skillbox рекомендует: Практический курс «Мобильный разработчик PRO».
Фильтрация уникальных значений
МАССИВЫ
Тип объекта Set был введен в ES6, вместе с ..., spread-оператором, мы можем использовать его для создания нового массива, в котором содержатся лишь уникальные значения.
const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Result: [1, 2, 3, 5]
В обычной ситуации для выполнения той же операции нужно гораздо больше кода.
Этот прием работает для массивов, содержащих примитивные типы: undefined, null, boolean, string и number. Если вы работаете с массивом, содержащим объекты, функции или дополнительные массивы, вам понадобится другой подход.
Длина кэш-массива в циклах
ЦИКЛЫ
Когда вы изучаеете for для циклов, то следуете стандартной процедуре:
for (let i = 0; i < array.length; i++){
console.log(i);
}
Тем не менее, при таком синтаксисе цикл for повторно проверяет длину массива при каждой итерации.
Иногда это может быть полезно, но в большинстве случаев эффективнее кэшировать длину массива, что потребует одного обращения к нему. Мы можем сделать это путем определения переменной длины, где задать переменную i, например, так:
for (let i = 0, length = array.length; i < length; i++){
console.log(i);
}
В принципе, почти то же самое, что и выше, но при увеличении размера цикла мы получим значительную экономию времени.
Оценка короткого замыкания (оценка Маккарти)
УСЛОВНЫЕ ОПЕРАТОРЫ
Тернарный оператор — быстрый и эффективный способ написать простые (а иногда и не очень простые) conditional statements:
х> 100? «больше 100»: «меньше 100»;
х> 100? (x> 200? «больше 200»: «между 100-200»): «меньше 100»;
Но иногда даже тернарный оператор сложнее, чем требуется. Вместо него мы можем использовать ‘and’ && и ‘or’ || логические операторы для оценки некоторых выражений еще более кратким способом. Его часто называют «коротким замыканием» или «оценкой короткого замыкания».
Как это работает
Скажем, мы хотим вернуть только одно из двух или более условий.
Использование && вернет первое false значение. Если каждый операнд оценивается как true, то будет возвращено последнее вычисленное выражение.
let one = 1, two = 2, three = 3;
console.log(one && two && three); // Result: 3
console.log(0 && null); // Result: 0
Использование || позволит вернуть первое true значение. Если каждый операнд оценивается как false, то будет возвращено последнее вычисленное значение.
let one = 1, two = 2, three = 3;
console.log(one || two || three); // Result: 1
console.log(0 || null); // Result: null
Пример 1
Скажем, мы хотим вернуть length переменной, но не знаем ее тип.
В этом случае можно использовать if/else для проверки того, что foo — подходящий тип, но этот способ может оказаться слишком долгим. Поэтому лучше возьмем наше «короткое замыкание».
return (foo || []).length;
Если переменная foo имеет подходящую length, то она и будет возвращена. В противном случае мы получим 0.
Пример 2
Были ли у вас проблемы с доступом к вложенному объекту? Вы можете не знать, существует ли объект или одно из его подсвойств, и это может привести к проблемам.
К примеру, мы хотели получить доступ к свойству data в this.state, но data не определено, пока наша программа не вернет запрос на выборку.
В зависимости от того, где мы его используем, вызов this.state.data может помешать запуску приложения. Чтобы решить проблему, мы могли бы обернуть это в условное выражение:
if (this.state.data) {
return this.state.data;
} else {
return 'Fetching Data';
}
Более подходящим вариантом будет использование оператора «or».
return (this.state.data || 'Fetching Data');
Мы не можем изменить код выше, чтобы использовать &&. Оператор 'Fetching Data' && this.state.data вернет this.state.data независимо от того, является он undefined или нет.
Опциональная цепочка
Можно предложить использовать опциональную цепочку при попытке вернуть свойство глубоко в древовидную структуру. Так, символ знака вопроса? может использоваться для извлечения свойства, только если оно не равно нулю (null).
Например, мы могли бы выполнить рефакторинг примера выше, получив this.state.data?.. (). То есть data возвращается лишь в том случае, если значение не null.
Или, если важно, определено ли state или нет, мы могли бы вернуть this.state?.data.
Преобразование в Boolean
ПРЕОБРАЗОВАНИЕ ТИПОВ
Кроме обычных логических функций true и false, JavaScript также рассматривает все другие значения как truthy или falsy.
Пока не указано иное, все значения в JavaScript — truthy, за исключением 0, "", null, undefined, NaN и, конечно, false. Последние являются falsy.
Мы можем легко переключаться между теми и другими, используя оператор !, который также преобразует тип в логический.
const isTrue = !0;
const isFalse = !1;
const alsoFalse = !!0;
console.log(true); // Result: true
console.log(typeof true); // Result: "boolean"
Преобразование в строку
ПРЕОБРАЗОВАНИЕ ТИПОВ
Быстрое преобразование целого числа в строку можно выполнить следующим образом.
const val = 1 + "";
console.log(val); // Result: "1"
console.log(typeof val); // Result: "string"
Преобразование в целое число
ПРЕОБРАЗОВАНИЕ ТИПОВ
Обратное преобразование выполняем так.
let int = "15";
int = +int;
console.log(int); // Result: 15
console.log(typeof int); Result: "number"
Этот способ может быть использован и для преобразования логического типа данных boolean в обычные числовые значения, как показано ниже:
console.log(+true); // Return: 1
console.log(+false); // Return: 0
Могут быть ситуации, когда + будет интерпретироваться как оператор конкатенации, а не сложения. Во избежание этого стоит использовать тильды: ~~. Этот оператор эквивалентен выражению -n-1. К примеру, ~ 15 равно -16.
Использование двух тильд подряд сводит на нет операцию, потому что — (- — n — 1) — 1 = n + 1 — 1 = n. Другими словами, ~ -16 равно 15.
const int = ~~"15"
console.log(int); // Result: 15
console.log(typeof int); Result: "number"
<Quick Powers
ОПЕРАЦИИ
Начиная с ES7, можно использовать оператор возведения в степень ** в качестве сокращения для степеней. Это гораздо быстрее, чем использование Math.pow (2, 3). Вроде просто, но в список приемов этот момент включен, поскольку далеко не везде он упоминается.
console.log(2 ** 3); // Result: 8
Не стоит путать его с символом ^, который обычно используется для возведения в степень. Но вот в JavaScript это оператор XOR.
До ES7 сокращение ** можно было применять только для степеней с основанием 2 с использованием оператора побитового сдвига влево <<:
Math.pow(2, n);
2 << (n - 1);
2**n;
К примеру, 2 << 3 = 16 эквивалентно выражению 2 ** 4 = 16.
Float в целое число
ОПЕРАЦИИ / ПРЕОБРАЗОВАНИЕ ТИПОВ
При необходимости преобразовать float в целое число можно воспользоваться Math.floor(), Math.ceil() или Math.round(). Но есть и более быстрый путь, для этого используем |, то есть оператор OR.
console.log(23.9 | 0); // Result: 23
console.log(-23.9 | 0); // Result: -23
Поведение | в значительной степени зависит от того, имеете ли вы дело с положительными или отрицательными числами, поэтому этот способ подходит только в том случае, если вы уверены в том, что делаете.
n | 0 удаляет все, что идет после десятичного разделителя, усекая число с плавающей точкой до целого числа.
Вы можете получить тот же эффект округления, используя ~~. После принудительного преобразования в целое число значение остается неизменным.
Убираем замыкающие числа
Оператор OR можно использовать для того, чтобы убрать любое количество цифр из числа. Это означает, что нам не нужно преобразовывать типы, как здесь:
let str = "1553";
Number(str.substring(0, str.length - 1));
Вместо этого просто прописываем:
console.log(1553 / 10 | 0) // Result: 155
console.log(1553 / 100 | 0) // Result: 15
console.log(1553 / 1000 | 0) // Result: 1
Автоматическое связывание
КЛАССЫ
Стрелочные обозначения ES6 можно использовать в методах класса, и при этом подразумевается привязка. Благодаря этому можно попрощаться с повторяющимися выражениями, такими как this.myMethod = this.myMethod.bind (this)!
import React, { Component } from React;
export default class App extends Compononent {
constructor(props) {
super(props);
this.state = {};
}
myMethod = () => {
// This method is bound implicitly!
}
render() {
return (
<>
<div>
{this.myMethod()}
</div>
</>
)
}
};
Обрезка массива
МАССИВЫ
Если вам необходимо убрать значения из массива, то есть более быстрые методы, чем splice().
К примеру, если вы знаете размер оригинального массива, то можете переопределить его свойство length следующим образом:
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.length = 4;
console.log(array); // Result: [0, 1, 2, 3]
Но есть и еще один метод, причем более быстрый. Если для вас имеет значение именно скорость, то вот наш выбор:
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array = array.slice(0, 4);
console.log(array); // Result: [0, 1, 2, 3]
Вывод последнего значения (значений) массива
МАССИВЫ
Этот прием требует использования метода slice().
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(array.slice(-1)); // Result: [9]
console.log(array.slice(-2)); // Result: [8, 9]
console.log(array.slice(-3)); // Result: [7, 8, 9]
Форматирование JSON-кода
JSON
Возможно, вы уже использовали JSON.stringify. Знаете ли вы, что он помогает форматировать ваш JSON?
Метод stringify () принимает два необязательных параметра: функцию replacer, которую можно использовать для фильтрации отображаемого JSON, и значение space.
console.log(JSON.stringify({ alpha: 'A', beta: 'B' }, null, 't'));
// Result:
// '{
// "alpha": A,
// "beta": B
// }'
Вот и все, надеюсь, что все указанные приемы были полезны. А какие хитрости знаете вы? Напишите их в комментариях.
Skillbox рекомендует:
- Двухлетний практический курс «Я — веб-разработчик PRO».
- Онлайн-курс «С#-разработчик с 0».
- Практический годовой курс «PHP-разработчик с 0 до PRO».
Автор: fokus-lop