
Всем привет! Меня зовут Леша, я фронтенд-разработчик. Крашу кнопочки, пишу js скрипты, веду канал в TG https://t.me/frontend_tales (подписывайтесь, стараюсь выкладывать полезный материал).
В этой статье хотел бы поделиться с вами лайфхаками JavaScript, которые, возможно, помогут вам понять тонкости языка и улучшить ваш код. В общем, статья рассчитана на джуниоров и мидлов, сеньорам возможно будет скучно, но рады всем. Начнем!
1. Разделитель числа
В числах можно использовать _ которое помогает улучшить читаемость чисел в коде.
const sixBillion = 6000000000 // Очень трудно читать const sixBillion2 = 6000_000_000 // Читать намного легче console.log(sixBillion2) // 6000000000 // В вычислениях тоже можно использовать const sum = 1000 + 6000_000_000 // 6000001000
2. Оператор ? для упрощения && и тернарных операторов
Например, у нас есть код, который мы хотим упростить:
const obj = null console.log(obj && obj.name) const title1 = document.querySelector('.title') const title = title1 ? title.innerText : undefined
Перепишем код с использованием оператора ?:
const obj = null console.log(obj?.name) const title1 = document.querySelector('.title') const title = title1?.innerText
3. BigInt для решения задач по вычислению больших целых чисел
К сожалению, корректность вычисления чисел в JS, превышающих Number.MAX_SAFE_INTEGER (9007199254740991), не гарантирована, это очень грустно.
Например:
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true // Math.pow(2, 53) => 9007199254740992 // Math.pow(2, 53) + 1 => 9007199254740992
Для вычисления больших чисел советую использовать BigInt. Это позволит избежать вычислительных ошибок.
BigInt(Math.pow(2, 53)) === BigInt(Math.pow(2, 53)) + BigInt(1) // false
4. Чем можно заменить оператор in
Чтобы узнать, существует ли свойство у объекта, обычно мы используем оператор in, но можно еще использовать obj.hasOwnProperty().
Оба они имеют свои недостатки:
Оператор
inпроверяет наличие свойства в объекте, включая свойства, унаследованные от прототипа. Это может привести к нежелательным результатам, если вы хотите проверить только наличие свойс��ва в самом объекте, а не в его прототипе.Метод
obj.hasOwnProperty()проверяет наличие свойства только в самом объекте, и не учитывает свойства, унаследованные от прототипа. Однако, этот метод не работает корректно, если объект переопределяет методhasOwnProperty. В таком случае, вызовobj.hasOwnProperty()может привести к ошибке или неправильному результату.Оба подхода не учитывают свойства, которые могут быть доступны через цепочку прототипов. Если вам нужно проверить наличие свойства в объекте, включая его прототипы, вам придется использовать другие методы, такие как
Object.getPrototypeOf()илиObject.prototype.isPrototypeOf().Использование
inиobj.hasOwnProperty()может быть неудобным и неэффективным при работе с большими объектами или вложенными структурами данных. Это может привести к необходимости выполнять множество проверок и вызовов методов, что может замедлить выполнение программы.
Небольшие примеры:
// Оператор in const obj = { name: 'John', age: 25 }; console.log('name' in obj); // true console.log('gender' in obj); // false // Проверка наличия свойства в прототипе объекта console.log('toString' in obj); // true // Метод obj.hasOwnProperty() const obj = { name: 'John', age: 25 }; console.log(obj.hasOwnProperty('name')); // true console.log(obj.hasOwnProperty('gender')); // false // Проверка наличия свойства в прототипе объекта console.log(obj.hasOwnProperty('toString')); // false
Есть еще один оператор Object.hasOwn(). Он удобнее и безопаснее, чем метод obj.hasOwnProperty().
const object1 = { prop: 'exists', }; console.log(Object.hasOwn(object1, 'prop')); // Expected output: true console.log(Object.hasOwn(object1, 'toString')); // Expected output: false console.log(Object.hasOwn(object1, 'undeclaredPropertyValue')); // Expected output: false
5. # для объявления частных свойств
Раньше для того чтобы показать что поле приватное мы добавляли _ , но теперь можно использовать #:
class Person { #money=1 constructor (name) { this.name = name } get money () { return this.#money } set money (money) { this.#money = money } showMoney () { console.log(this.#money) } } const p1 = new Person('fatfish') console.log(p1.money) // 1 // p1.#money = 2 // Таким способом нельзя изменить #money p1.money = 2 console.log(p1.money) // 2 console.log(p1.#money)
6. ?? вместо ||
Используйте ?? вместо ||, чтобы определить, является ли значение в левой части оператора null или undefined, а затем вернуть значение в правой части.
const name = ''; const defaultName = 'John'; const result = name ?? defaultName; console.log(result); // '' const age = 0; const defaultAge = 25; const result2 = age ?? defaultAge; console.log(result2); // 0
В примере выше, оператор ?? возвращает значение переменной слева от него, если это значение не равно null или undefined.
В противном случае, если значение переменной слева от ?? равно null или undefined, оператор возвращает значение переменной справа от него.
7. Преобразование String в Number
Многие почему-то используют для преобразования string в number функцию parseInt(), когда можно использовать только оператор +
const num = parseInt("1000"); // и const num = +"1000";
8. Сокращенный вариант для Math.floor при округлении чисел
Вместо функции Math.floor() для округления числа можно использовать оператор ~~:
Math.floor(5.25) // 5.0 // или ~~5.25 // 5.0
9. Преобразование значения в Boolean
Для преобразования любого значения в Boolean нужно использовать двойной восклицательный знак !!:
!!true // true !!2 // true !![] // true !!"Test" // true !!false // false !!0 // false !!"" // false
10. Объединение массивов
Для объединения массивов хорошо использовать spread (…) оператор, вместо метода concat():
const nums1 = [1, 2, 3]; const nums2 = [4, 5, 6]; let newArray = nums1.concat(nums2); // spread newArray = [...nums1, ...nums2]; // можно добавлять значения в массив numbers = [...numbers, 4, 5];
11. Удаление повторяющихся элементов из массива
Удаляем через Set() - множество:
const numbers = [1, 1, 20, 3, 3, 3, 9, 9]; const uniqueNumbers = [...new Set(numbers)]; // [1, 20, 3, 9]
12. Изменение мест двух переменных без использования третьей
В JavaScript можно “оторвать” значения от массива с помощью деструктуризации. Этот прием также применим, если нужно поменять местами две переменные без вспомогательной третьей.
let x = 1; let y = 2; let temp = x; x = y; y = temp; [x, y] = [y, x];
13. document.designMode
Связанный с интерфейсным JavaScript, designMode позволяет редактировать любой контент на странице. Просто откройте консоль браузера и введите следующее:
document.designMode = 'on';
Обязательно попробуйте, очень классная штука)
14. Быстрое преобразование Float в Integer
Если вы хотите преобразовать число с плавающей точкой в целое число, вы можете использовать Math.floor(), Math.ceil() или Math.round().
Но есть также более быстрый способ обрезать число с плавающей точкой до целого числа, используя | оператор побитового ИЛИ.
console.log(23.9 | 0); // 23 console.log(-23.9 | 0); // -23
15. Обрезание массива
Если вы хотите удалить значения из конца массива деструктивно, есть более быстрые альтернативы, чем использование splice().
Пример:
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; array.length = 4; console.log(array); // [0, 1, 2, 3]
Кстати, часто на собесах спрашивают, что будет если мы свойству length присвоим значение.
16. Получить n последних элементов массива
Метод массива slice() может принимать отрицательные целые числа, и при наличии он будет принимать значения с конца массива, а не с начала.
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log(array.slice(-1)); // [9] console.log(array.slice(-2)); // [8, 9] console.log(array.slice(-3)); // [7, 8, 9]
Я не предлагаю использовать все возможности, которые описаны в этой статье. Некоторые способы могут нанести вред коду, но знать их нужно. Спасибо!