вторник, 27 июня 2017 г.

19 методов сокращенного кодирования JavaScript

Эту статью действительно стоит прочитать любому разработчику JavaScript. Я написал ее как справочник для обучения сокращенным методам кодирования JavaScript, о которых я узнал за свои годы опыта. Для того что бы помочь вам понять что происходит, я включил также длинные версии кода, что бы понять все детали.
1. Тернарный оператор
Этот код позволяет писать вам более лаконичные выражения if-else и помещать их в одну строку.
Обычный вариант:
const x = 20;
let big;

if (x > 10) {
    big = true;
} else {
    big = false;
}

Сокращенный вариант:
const big = x > 10 ? true : false;

Вы также можете вложить одно такое выражение в другое:
const big = x > 10 ? " greater 10" : x < 5 ? "less 5" : "between 5 and 10";

2. Вычисление условий
Когда мы устанавливаем значение перенменной как значение другой переменной, вы должны убедится что источник не null и не пустой. Вы можете написать длиное выражение с множественными условиями для проверки этого, иои использовать сокращенную версию.
Обычный вариант:
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
     let variable2 = variable1;
}

Сокращенный вариант:
const variable2 = variable1  || 'new';

Не верите? Проверьте сами (вставте этот код в es6console):
let variable1;
let variable2 = variable1  || '';
console.log(variable2 === ''); // prints true

variable1 = 'foo';
variable2 = variable1  || '';
console.log(variable2); // prints foo

3. Объявление переменных
Хорошей практикой является объявление переменных вначале функции. Сокращенная весрия позволит сохранить много времени и места если вы будете объявлять много переменных за один раз.
Обычный вариант:
let x;
let y;
let z = 3;

Сокращенный вариант:
let x, y, z=3;

4. Присутствие if
Это может показаться тривиальным, но все таки стоит обратить внимание. Когда вы пользуетесь if, иногда оператор сравнения может быть опущен.
Обычный вариант:
if (likeJavaScript === true)

Сокращенный вариант:
if (likeJavaScript)

Вот другой пример. Если “a” НЕ true, до делаем что-то.
Обычная версия:
let a;
if ( a !== true ) {
// что-то делаем...
}

Скоращенная версия:
let a;
if ( !a ) {
// что-то делаем...
}

5. Циклы в JavaScript
Этот маленький совет действительно полезен, если вы хотите использовать обычный JavaScript и не полагаетесь на внешние библиотеки, такие как jQuery или lodash.
Обычная версия:
for (let i = 0; i < allImgs.length; i++)

Сокращенная версия:
for (let index in allImgs)

Сокращенная версия для Array.forEach:
function logArrayElements(element, index, array) {
  console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[2] = 9

6. Упрощения
Вместо того что бы писать шесть строк кода для того что бы установить значение по умолчанию если требуемые параметр пустой, можно просто использовать для сокращения логический оператор и выполнять ту же логику одной строчкой.
Обычный вариант:
let dbHost;
if (process.env.DB_HOST) {
  dbHost = process.env.DB_HOST;
} else {
  dbHost = 'localhost';
}

Сокращенный вариант:
const dbHost = process.env.DB_HOST || 'localhost';

7. Экспоненты десятичной базы
Вы возможно видели такой способ. Это замечательный способ писать большие числа без большого количества нулей. Например 1е7 значит 1 за которым следует семь нулей. Число представленно в десятичной системе (которую JavaScript интерпретирует как плавающий тип) и эквивалентно 10,000,000.
Обычный вариант:
for (let i = 0; i < 100000; i++) {}

Сокращенный вариант:
for (let i = 0; i < 1e5; i++) {}

// Все выражения истинны
1e0 === 1;
1e1 === 10;
1e2 === 100;
1e3 === 1000;
1e4 === 10000;
1e5 === 100000;

8. Сокращения для свойств объекта
Литералы объявления объектов в JavaScript делают нашу жизнь проще. ES6 обеспечивает еще более простой способ управления свйствами объекта. Если имя свойства такое же как и его значение, вы можете ипользовать упрощенную нотацию.
Обычный вариант:
const obj = { x:x, y:y };

Сокращенный вариант:
const obj = { x, y };

9. Сокращения для функций стрелок.
Классические функции удобны для чтения и написания в простой форме, но когда они становятся многословными и более сложными, то вы начиаете их помещать в вызовы вложенных функций.
Обычный вариант:
function sayHello(name) {
  console.log('Hello', name);
}

setTimeout(function() {
  console.log('Loaded')
}, 2000);

list.forEach(function(item) {
  console.log(item);
});

Сокращенный вариант:
sayHello = name => console.log('Hello', name);

setTimeout(() => console.log('Loaded'), 2000);

list.forEach(item => console.log(item));

10. Сокращения для неявно возвращаемого значения
Return – это ключевое слово для возврата финального результата фунции. Функции стрелки с однострочным выражением неявно вернут результат вычислений (у функции должны быть опущены фигурные скобки тела для того что бы можно было не указывать return).
Для возврата многострочного выражения (такого как объект), необходимо использовать круглые скобки вместо фигурных, и обернуть ими тело функции. Это позволит коду выполнится как одно выражение.
Обычный вариант:
function calcCircumference(diameter) {
  return Math.PI * diameter
}

Сокращенный вариант:
calcCircumference = diameter => (
  Math.PI * diameter;
)

11 Значения по умолчанию для параметров
Вы можете использовать выражение if для того что бы определить значение по умолчанию для параметров функции. В ES6 вы можете определить параметры по умолчанию непостредственно в объявлении функции.
Обычный вариант:
function volume(l, w, h) {
  if (w === undefined)
    w = 3;
  if (h === undefined)
    h = 4;
  return l * w * h;
}

Сокращенный вариант:
volume = (l, w = 3, h = 4 ) => (l * w * h);

volume(2) //output: 24

12. Литералы шаблонов
А вы не пробовали использовать + для объединения переменных в строку? Неужто нету более простого способа сделать это? Если вы можете использовать ES6, то вам повезло. Все что нужно использовать кавычки и выражение ${} в которое нужно добавить ваши переменные.
Обычный вариант:
const welcome = 'You have logged in as ' + first + ' ' + last + '.'

const db = 'http://' + host + ':' + port + '/' + database;

Сокращенный вариант:
const welcome = `You have logged in as ${first} ${last}`;

const db = `http://${host}:${port}/${database}`;

13. Удаление присваиваний
Если вы работаете с любым популярным фреймворком, то есть болшой шанс, что вы используете массивы или данные в форме объектов, для того что бы передавать информацию между компонентами и API. Как только данные доберутся до компонента, вам нужно их распаковать.
Обычный вариант:
const observable = require('mobx/observable');
const action = require('mobx/action');
const runInAction = require('mobx/runInAction');

const store = this.props.store;
const form = this.props.form;
const loading = this.props.loading;
const errors = this.props.errors;
const entity = this.props.entity;

Сокращенный вариант:
import { observable, action, runInAction } from 'mobx';

const { store, form, loading, errors, entity } = this.props;

Вы можете даже присвоить свои собственные имена:
const { store, form, loading, errors, entity:contact } = this.props;

14. Сокращения для многострочного текста.
Если вам доводилось писать многострочный текст, то это может вам помочь:
Обычный вариант:
const lorem = 'Lorem ipsum dolor sit amet, consectetur\n\t'
    + 'adipisicing elit, sed do eiusmod tempor incididunt\n\t'
    + 'ut labore et dolore magna aliqua. Ut enim ad minim\n\t'
    + 'veniam, quis nostrud exercitation ullamco laboris\n\t'
    + 'nisi ut aliquip ex ea commodo consequat. Duis aute\n\t'
    + 'irure dolor in reprehenderit in voluptate velit esse.\n\t'

Но есть и более простой вариант – использовать кавычки.
Сокращенный вариант:
const lorem = `Lorem ipsum dolor sit amet, consectetur
    adipisicing elit, sed do eiusmod tempor incididunt
    ut labore et dolore magna aliqua. Ut enim ad minim
    veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute
    irure dolor in reprehenderit in voluptate velit esse.`

15. Оператор расширения
Оператор расширения (spread operator) появился в ES6, его можно использовать в нескольких случаях для того что бы сделать код более удобным для использования. Он может быть использован для того что бы заместить функции массива. Оператор расширения это просто серия из трех точек.
Обычная вариант
// объединение массивов
const odd = [1, 3, 5];
const nums = [2 ,4 , 6].concat(odd);

// клонирование массивов
const arr = [1, 2, 3, 4];
const arr2 = arr.slice()

Сокращенный вариант:
// объединение массивов
const odd = [1, 3, 5 ];
const nums = [2 ,4 , 6, ...odd];
console.log(nums); // [ 2, 4, 6, 1, 3, 5 ]

// клонирование массивов
const arr = [1, 2, 3, 4];
const arr2 = [...arr];

В отличие от функции concat(), вы можете использовать оператор расширения для того что бы вставить другой массив в люое место вашего массива.
const odd = [1, 3, 5 ];
const nums = [2, ...odd, 4 , 6];
Вы также можете комбинировать оператор расширения с нотацией удаления:
const { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a) // 1
console.log(b) // 2
console.log(z) // { c: 3, d: 4 }

16. Сокращения для обязательного параметра
По умолчанию, JavaScript установит undefined для тех параметров, которые не былі указаны в вызове. Нектороые другие языки в таких случаях бросают ошибку или предупреждение. Для того что бы принудить указать параметр, вы можете использовать if для того что бы бросить ошибку в случае есть параметр неопределен, или же можете использовать прием показанный ниже:
Обычный вариант:
function foo(bar) {
  if(bar === undefined) {
    throw new Error('Missing parameter!');
  }
  return bar;
}

Сокращенный вариант:
mandatory = () => {
  throw new Error('Missing parameter!');
}

foo = (bar = mandatory()) => {
  return bar;
}

17. Сокращения для Array.find
Если вы когда-нибудь занимались написанием функции поиска на чистом JavaScript, то вероятно использовали цикл. В ES6 была добавлена новая встроеная функция поиска.
Обычный вариант:
const pets = [
  { type: 'Dog', name: 'Max'},
  { type: 'Cat', name: 'Karl'},
  { type: 'Dog', name: 'Tommy'},
]

function findDog(name) {
  for(let i = 0; i<pets.length; ++i) {
    if(pets[i].type === 'Dog' && pets[i].name === name) {
      return pets[i];
    }
  }
}

Сокращенный вариант:
pet = pets.find(pet => pet.type ==='Dog' && pet.name === 'Tommy');
console.log(pet); // { type: 'Dog', name: 'Tommy' }

18 Сокращение Object [key]
Вы знаете что Foo.bar может быть написан как Foo['bar']? Во первых нет ни одной причины почему так нельзя писать. Однако такая нотация позволяет писать код который потом можно использовать повторно.
Рассмотрим простейший пример функции валидации:
function validate(values) {
  if(!values.first)
    return false;
  if(!values.last)
    return false;
  return true;
}

console.log(validate({first:'Bruce',last:'Wayne'})); // true

Эта функция отлично делает свою работу. Однако давайте рассмотрим случай, когда у нас слишком много форм, для которых нужно сделать валидацию для разных полей и правил. Не было бы здорово сделать нашу функцию более гибкой, которую можно конфигурировать в процессе выполнения.
Сокращенный вариант:
// правила валидации объекта
const schema = {
  first: {
    required:true
  },
  last: {
    required:true
  }
}

// универсальная функция валидации
const validate = (schema, values) => {
  for(field in schema) {
    if(schema[field].required) {
      if(!values[field]) {
        return false;
      }
    }
  }
  return true;
}


console.log(validate(schema, {first:'Bruce'})); // false
console.log(validate(schema, {first:'Bruce',last:'Wayne'})); // true
Теперь у нас есть функция валидации, которую можно использовать повторно для всех форм без необходимость переписывать код.
19. Сокращения для двойного битового отрицания
Битовые операции - это  то что всегда учат новички, но потом как правиль нигде не используют. Кто же хочеть работать с нулями и единицами, если вы не работаете с бинарными данными?
Но есть пожалуй одно очень практическое применение оператора двойного битового отрицания. Вы можете использовать его вместо Math.floor(). Преимуществом такого использования будет более высокая скорость выполнения. Вы можете почитать подробнее о битовых операциях здесь.
Обычный вариант:
Math.floor(4.9) === 4  //true
Сокращенный вариант:
~~4.9 === 4  //true
20. Предложите еще?
Мне действительно хочеться узнать о новых методах, поэтому оставляйте их в своих коментариях.