Подписывайтесь на мой твиттер, там всегда что-нибудь интересное!

Лучшие советы и уловки JavaScript

По факту эти техники сохранят вам кучу времени.

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

Это переводы трех статей, которые действительно помогут вам писать лучше, быстрее и продуктивнее.

Перевод первой статьи Learn these neat JavaScript tricks in less than 5 minutes

Очистка и сокращение массива

Вот простой способ очистки или сокращения массива его переназначения. Вы можете просто поменять его length свойство:

const arr = [11, 22, 33, 44, 55, 66];
  // Сокращение
arr.length = 3;
console.log(arr); //=> [11, 22, 33]
  // Очистка
arr.length = 0;
console.log(arr); //=> []
console.log(arr[2]); //=> undefined

Имитация параметров с помощью деструктуризации

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

doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 });
function doSomething(config) {  
    const foo = config.foo !== undefined ? config.foo : 'Hi';  
    const bar = config.bar !== undefined ? config.bar : 'Yo!';  
    const baz = config.baz !== undefined ? config.baz : 13;  // ...}

Это старый, но эффективный паттерн, который пытается имитировать именованные параметры в JavaScript. Вызов функции выглядит хорошо. С другой стороны, объект конфигурация содержит логику, которая занимает ну уж слишком много писанины. А вот помощью ES2015 деструктуризации, вы можете обойти этот недостаток:

function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 }) {  // ...}
И если вам нужно сделать конфиг объекта опциональным, но это тоже очень просто:
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {  // ...}

Деструктуризация объекта для элементов массива

Назначайте элементы массива индивидуальным переменным с помощью деструктуризации объектов:

const csvFileLine = '1997,John Doe,US,john@doe.com,New York';
const { 2: country, 4: state } = csvFileLine.split(',');

Асинхронные функции с async/await

Да, есть возможно обождать множественную асинхронную функцию, используя Promise.all:

await Promise.all([anAsyncCall(), thisIsAlsoAsync(), oneMore()])

Создание пустых объектов

Вы можете создать 100% пустой объект, который не будет наследовать какие-либо свойства или методы из изначального объекта (например, constructortoString() и так далее).

const pureObject = Object.create(null);
console.log(pureObject); //=> {}
console.log(pureObject.constructor); //=> undefined
console.log(pureObject.toString); //=> undefined
console.log(pureObject.hasOwnProperty); //=> undefined

Форматирование кода JSON

JSON.stringify может не просто конвертировать объект в строку. А так же может сделать красивую выдачу JSON:

const obj = {
foo: { bar: [11, 22, 33, 44], baz: { bing: true, boom: ‘Hello’ } }
};
// Третий параметр это чисто пробелов, используемое для украшения JSON вывода
JSON.stringify(obj, null, 4);
// =>”{
// => “foo”: {
// => “bar”: [
// => 11,
// => 22,
// => 33,
// => 44
// => ],
// => “baz”: {
// => “bing”: true,
// => “boom”: “Hello”
// => }
// => }
// =>}”

Удаление дублирующихся элементов из массива

Используя сеты ES2015 вместе с оператором расширения, вы легко можете удалить дублирующиеся элементы из массива:

const removeDuplicateItems = arr => [new Set(arr)];
removeDuplicateItems([42, 'foo', 42, 'foo', true, true]);
//=> [42, "foo", true]

Слияние многоуровневых массивов

Вообще слияние многоуровневых массивов довольно тривиально с помощью оператора расширения:

const arr = [11, [22, 33], [44, 55], 66];
const flatArr = [].concat(…arr); //=> [11, 22, 33, 44, 55, 66]

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

function flattenArray(arr) {
  const flattened = [].concat(...arr);
  return flattened.some(item => Array.isArray(item)) ?      flattenArray(flattened) : flattened
;}
const arr = [11, [22, 33], [44, [55, 66, [77, [88]], 99]]];
const flatArr = flattenArray(arr);
//=> [11, 22, 33, 44, 55, 66, 77, 88, 99]

Перевод второй статьи 7 Hacks for ES6 Developers

Перетасовка переменных

Используйте деструктуризацию массивов для перетасовки переменных. Тут все будет понятно из кода:

let a = 'world', b = 'hello'
[a, b] = [b, a]
console.log(a) // -> hello
console.log(b) // -> world
// Да, это магия, детка!

Деструктуризация с async/await

И снова, деструктуризация массивов просто шедевральна. Вместе с async/await она делает невообразимые вещи.

const [user, account] = await Promise.all([
  fetch('/user'),
  fetch('/account')
])

Дебаггинг

Для всех кто любит дебаггинг с помощью console.log, вот вам крутой пример и да, я слышал про console.table:

const a = 5, b = 6, c = 7
console.log({ a, b, c })
// выдаёт объект:
// {
//    a: 5,
//    b: 6,
//    c: 7
// }

Однострочники

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

// Найти максимальное значение
const max = (arr) => Math.max(…arr);
max([123, 321, 32]) // вывод: 321
// Сумма массива
const sum = (arr) => arr.reduce((a, b) => (a + b), 0)
sum([1, 2, 3, 4]) // вывод: 10

Конкатенация(слияние) массивов

Вообще оператор расширения может использоваться вместо concat:

const one = ['a', 'b', 'c']
const two = ['d', 'e', 'f']
const three = ['g', 'h', 'i']
// старый способ #1
const result = one.concat(two, three)
// старый способ #2
const result = [].concat(one, two, three)
// новый
const result = [...one, ...two, ...three]

Клонирование

Клонирование массивов и объектов с легкостью:

const obj = { …oldObj }
const arr = [ …oldArr ]

Именованные параметры

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

const getStuffNotBad = (id, force, verbose) => {
  ...do stuff
}
const getStuffAwesome = ({ id, name, force, verbose }) => {
  ...do stuff
}
// Где то там в коде, что такое вообще true, true и к чему оно?
getStuffNotBad(150, true, true)
// А вот уже по другому... I ❤ JS!!!
getStuffAwesome({ id: 150, force: true, verbose: true })

И третья, бонусная статья аж 2013-го года. Все эти практики уже давно знакомы, но все же самые интересные из них не помешает закрепить.

Перевод статьи Javascript Hacks for Hipsters

Вызов метода

Я реально не люблю блоки if/else и это довольно полезный трюк для вызова нужной функции, основываясь на булиных значениях.

// Скукота
if (success) {
  obj.start();
} else {
  obj.stop();
}

// По-хипстерски
var method = (success ? 'start' : 'stop');
obj[method]();

Совмещаем строки

Известный факт, что строки подобны другим строкам. И рано или поздно вы бы захотели связать две или более из них. Мне действительно не нравится работа с плюсом, по-этому join() приходит на помощь.

['first', 'name'].join(' '); // = 'first name';

['milk', 'coffee', 'sugar'].join(', '); // = 'milk, coffee, sugar'

Дефолтный оператор

JavaScript сам по себе не знает, что содержит объект. Иногда вы получаете его как аргумент функции, в другой раз вы можете прочесть его из сети или из файла конфигурации. В любом случае, вы можете использовать || оператор, чтобы использовать второй аргумент, если первый выдает false.

// Ставим по дефолту 'No name' когда myName пуст (или null, или undefined)
var name = myName || 'No name';


// Убеждаемся, есть ли у нас объект options
var doStuff = function(options) {
  options = options || {};
  // ...
};

Оператор на страже точности &&

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

// Скучно
if (isThisAwesome) {
  alert('yes'); // нет
}

// Отлично
isThisAwesome && alert('yes');

// Ещё один крутой подход
var aCoolFunction = undefined;
aCoolFunction && aCoolFunction(); // не запустится и не закрэшится