Глупые трюки с ES6

в 10:52, , рубрики: ES6, javascript, ненормальное программирование, синтаксис javascript, метки:

Это перевод статейки о некоторых не совсем очевидных прикольных возможностях, которые предоставляет ES6 стандарт JavaScript'а. В статье время от времени проходит нечто наркоманское, так что вполне возможно я не смог перевести всё достаточно качественно. Если нашли косяки, напишите мне об этом — поправлю.

{в оригинале здесь была какая-то непонятная гифка с обезьяной, которую я как-то не очень понял, оттого и не буду её здесь ставить}

Вот вам несколько методов на основе ES6, которые на самом деле не совсем трюки — просто, используя некоторые вещи из нового синтаксиса, мы можем неплохо сократить код, улучшить его читаемость, или, возможно, просто весело провести время. Я (автор оригинала, не автор этой статьи на хабре — прим. пер.) планирую собирать больше в этой статье, поэтому, пожалуйста, не стесняйтесь добавлять её в закладки и проверять время от времени. Ну и если у вас тоже есть какие-то забавные трюки, которые я не упоминаю здесь, пожалуйста, напишите об этом!

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

Деструктуризация — моя самая любимая часть синтаксиса ES6. Теперь она есть и в Node 6, так что это дело можно использовать и на фронтенде, и на серверной стороне. Для больших подробностей можно почитать разъяснение этого дела на сайте Mozilla (там тоже на русском, кстати), если вы не знаете основу, а для тех, кто МБ/НЧ — это возможность легко назначать определённым переменным какие-то значения во вложенных объектах.

Парочка простых примеров:

// можно деструктурировать массивы
const [a, b] = [1,2]; // a = 1, b = 2

// можно деструктурировать ключи в объектах
const { a } = { a: 3 }; // a = 3

// даже параметры функций
function foo({ a }) {
  console.log(a);
}

foo({ a: 4 }); // выведет 4

Переименование

Одна из фишек деструктуризации, о которой вы, возможно, не знаете — это возможность переименования по ходу дела. Если вы использовали ES6 модули, вы можете знать, как работает оператор импорта при переименовании импортированных объектов и, возможно, задавались вопросом, почему так не получается делать при деструктуризации. Ну, там на самом деле просто чуток другой синтаксис:

// простое переименование для избежания коллизий или просто для красоты.
const first = 5;
const { first: second } = { first: 3 };

console.log(second); // выведет 3

// переименовать для другого API с использованием расширенного использования присваивания
function verifyUser({ userId: id }) {
  return User.update({ id, verified: true });
}

В сочетании с параметрами по умолчанию

Параметры по умолчанию позволяют вам указывать значения параметрам, которые не были переданы пользователем, но что если вы собирались деструктуризовать их, когда они приходят? Не проблема… У нас есть левая сторона присваивания (a.k.a. lvalue) с параметрами по умолчанию, так что вы можете использовать деструктуризацию и здесь!

function defaults({ a, b } = { a: 1, b: 2 }) {
  console.log('a', a); 
  console.log('b', b);
}

defaults();
// a 1
// b 2

defaults({ a: 42, b: 32 });
// a 42
// b 32

// Будьте осторожны с множественными параметрами!
// Вся правая сторона будет заменена вашими аргументами.
defaults({ a: 87 });
// a 87
// b undefined

Деструктуризация самого себя также может иметь значения по-умолчанию, так что мы можем смешать оба варианта!

function defaults({ a = 1, b = 2 } = {}) {
  console.log('a', a); 
  console.log('b', b);
}

defaults();
// a 1
// b 2

defaults({ a: 42, b: 32 });
// a 42
// b 32

// множественные параметры? Нет проблем, просто укажите то, что вы хотите изменить
defaults({ a: 87 });
// a 87
// b 2

Присваивания, ветвления и листья

Вы даже можете деструктурировать глубокий объект или массив! Но промежуточные ключи объектов не будут присвоены в это время. Что делать, если вы хотите присвоить какие-то промежуточные ключи и какой-то глубокий узел? Просто спросите о нём! Другими словами, как мы покажем в нижеидущем примере, вы можете просто объявить любую переменную, которую хотите (промежуточное соединение в данном случае) и использовать её снова как спецификацию для перехода на другой уровень (промежуточный -> вложенный) (вот же-ж наркомания… — прим. пер.).

const {
  topLevel: {
    intermediate,    // объявление промежуточной
    intermediate: {
      nested         // объявление вложенной
    }
  }
} = {
  topLevel: {
    intermediate: {
      nested: 56
    }
  }
};

// intermediate is { nested: 56 }
// nested is 56

Идиоматические аргументы командной строки для Node

Node.js прекрасная вещь для написания скриптов. Для аргументов командной строки вы можете извлечь их из process.argv. Если вы делаете что-то сложное, или действительно нечто предназначение для использования людьми, лучше будет заюзать что-нибудь вроде yargs для их парсинга. Но… если у вас есть скрипт, который просто берёт небольшое количество аргументов, вы можете использовать деструктуризацию массива для того чтобы пропустить первые два аргумента (обычно путь к Node.js и путь к скрипту) и присвоить остальные переменным.

#!/usr/bin/env node

// пропустить первые два аргумента, которые являются node.js и этим скриптом
const [,,filepath] = process.argv;

doSomethingFSLike(filepath);

Расширенные литералы объектов

Обновления в синтаксисе литерала объекта реально классные, и мы сейчас заюзаем некоторые вышеприведённые примеры с использованием "коротких названий значений". Первая техника — это даже больше не трюк, а возможность избежать связывания, если вы в нём не нуждаетесь. Скажем, вы хотите видеть переменную или функцию извне, но также хотите использовать её внутри функций, которые вы экспортируете как вспомогательный объект. Техника объявления её вне возвращаемого объекта и вкладывание её ниже позволяет вам избежать связывания.

const moment = require('moment');
const PERIOD = moment.duration(3, 'days');

module.exports = {
  PERIOD,

  isWithinPeriod(test) {
    return moment().add(PERIOD).isAfter(test);
  },
};

/// В то же время, в нашем файле теста...

const timeUtils = require('./time-utils');

describe('timeUtils.isWithinPeriod', () => {
  it('ложно за пределами его собственного временного периода', () => {
    const beyondPeriod = moment().add(timeUtils.PERIOD).add(timeUtils.PERIOD);
    assert(timeUtils.isWithinPeriod(beyondPeriod) === false);
  });
});

Вместе с JSX

Окей, это не ES6 конечно, но вы можете использовать некоторые фичи ES6 вроде короткого значения свойства очень удобным образом вместе с JSX.

function WhySoManyProps(props) {
  const user = extractUser(props);
  const fudge = calculateFudge();
  const bits = computeBits();

  // Это тааак избыточно.
  return <SomeComponent user={user} fudge={fudge} bits={bits} />;
}

function Shorthand(props) {
  const user = extractUser(props);
  const fudge = calculateFudge();
  const bits = computeBits();

  // отправим все новые переменные, которые имеют такое же имя, как и свойства
  return <SomeComponent {...{ user, fudge, bits }} />;
}

Правда, такой подход не очень рекомендуют использовать в официальной документации к React.js — прим. переводчика.

Object.assign

Object.assign — это фантастическое новое дополнение, которое очень помогает сохранять вещи иммутабельными (или, по крайней мере, делать только эфемерные мутации к промежуточным объектам). Но знаете ли вы, что их можно устанавливать и для значений массивов в том числе?

const original = [0,1,2,3];
const copy = Object.assign([], original, { 2: 42 }); // [0,1,42,3]

console.log(original);
// [ 0, 1, 2, 3 ]

console.log(copy);
// [ 0, 1, 42, 3 ]

Ваши предложения?

Есть какие-то другие трюки, которые вам нравятся, и которые отсутствуют в данной статье? Поделитесь ими в комментариях!

Автор: saggid

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js