12 хитростей JavaScript, которых вы не найдете в большинстве уроков

0
5580

12 хитростей JavaScript, которых вы не найдете в большинстве уроков

Наша группа в телеграм Bookflow

Когда я начал изучать JavaScript, я составлял список хитростей, которые находил в чужом коде, на веб-сайтах, посвященных проверке кода, и в любых других местах, кроме учебных пособий, которые я использовал.

С тех пор я пополняю этот список, и в этой статье я поделюсь 12 советами, которые кажутся мне особенно умными или полезными.

Купон на 15% скидку
Coupon
Освой самый популярный язык программирования - JavaScript и научись применять его на практике!
More Less
Expires on: 01-04-2020

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

Итак, вот 12 изящных способов написания более лаконичного и производительного кода.

1. Фильтр уникальных значений

МАССИВЫ

Тип Set был введен в ES6, и наряду с оператором «spread» ... мы можем использовать его для создания нового массива с уникальными значениями.

const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [...new Set(array)];

До ES6 фильтрация уникальных значений потребовала бы гораздо больше кода, чем сейчас!

Этот трюк работает для массивов, содержащих примитивные типы: undefined, null, boolean, string и number. (Если бы у вас был массив, содержащий объекты, функции или дополнительные массивы, вам понадобился бы другой подход!)

2. Кешируем длину массива в циклах

ЦИКЛЫ

Когда нас учат циклам for, нам рекомендуется следовать этой стандартной структуре:

for (let i = 0; i < array.length; i++){
  console.log(i);
}

Однако, используя этот синтаксис, цикл for пересматривает длину массива при каждой итерации.

Иногда это может быть полезно, но в большинстве случаев лучше и эффективнее кэшировать длину массива, так что к ней нужно обратиться только 1 раз. Мы можем сделать это, определив переменную length

for (let i = 0, length = array.length; i < length; i++){
  console.log(i);
}

Этот код почти такой же лаконичный, как и приведенный выше, но он работает таким образом, что при увеличении размера массива мы не теряем время на перепроверку array.length.

3. Вычисление короткого замыкания

УСЛОВНЫЕ ОПЕРАТОРЫ

Тернарный оператор — это быстрый способ написать простые (а иногда и не очень простые) условные конструкции, например:

x > 100 ? 'Above 100' : 'Below 100';
x > 100 ? (x > 200 ? 'Above 200' : 'Between 100-200') : 'Below 100';

Но иногда даже тернарный оператор получается сложнее, чем нужно. Вместо него мы можем использовать логические операторы «и» && и «или» || для более точной оценки определенных выражений. Его часто называют «коротким замыканием».

Как это работает

Допустим, мы хотим вернуть только один из двух или более вариантов.

Использование && вернет первое false или ‘ложноe’ значение. Если каждый операнд оценивается как true, будет возвращено последнее вычисленное выражение.

let one = 1, two = 2, three = 3;
console.log(one && two && three); // Result: 3
console.log(0 && null); // Result: 0

Использование || вернет первое true или ‘правдивоe’ значение. Если каждый операнд оценивается как 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, оно будет возвращено. В противном случае вернется length пустого массива: 0.

Пример 2

Были ли у вас проблемы с доступом к вложенному объекту? Вы можете не знать, существует ли у объекта свойство или одно из под-свойств, и это может вызвать неприятные ошибки.

Допустим, мы хотели получить доступ к свойству data, которое находится внутри this.state, но data — undefined до тех пор, пока программа не вернет респонз.

В зависимости от того, где мы используем этот код, вызов this.state.data может помешать запуску нашего приложения. Чтобы обойти это, мы могли бы обернуть все в условное выражение:

if (this.state.data) {
  return this.state.data;
} else {
  return 'Fetching Data';
}

Это кажется довольно скучным. Оператор «или» предоставляет более краткое решение:

return (this.state.data || 'Fetching Data');

Мы не можем изменить код выше, чтобы использовать && . Утверждение 'Fetching Data' && this.state.data вернется this.state.data независимо от того, равно оно undefined или нет. Это потому, что ‘Fetching Data’ «правдиво», и поэтому && всегда будет пропускать его, когда он указан первым.

Новая предлагаемая фича: опциональная последовательность

В настоящее время существует предложение разрешить «опциональную последовательность» при попытке вернуть свойство, находящееся глубоко в древовидной структуре. Согласно предложению, символ вопросительного знака ? может использоваться для извлечения свойства, только если оно не null

Например, мы могли бы привести свой пример выше к this.state.data?.() — вернет data, только если оно не null .

Или, если мы сомневаемся в переменной state, мы могли бы вернуть this.state?.data.

Предложение в настоящее время находится на Stage 1 в качестве экспериментальной функции. Вы можете прочитать об этом тут, и можете использовать его в своем JavaScript через Babel, добавив @babel/plugin-proposal-optional-chaining в ваш .babelrc файл.

4. Преобразование в Boolean

ПРИВЕДЕНИЕ ТИПОВ

Помимо обычных логических значений true и false, JavaScript также обрабатывает все другие значения как «правдивые» или «ложные».

Если не указано иное, все значения в JavaScript являются «правдивыми» за исключением 0, "", null, undefined, NaN и, конечно false — которые являются «falsy».

Мы можем легко переключаться между true и false, используя отрицательный оператор  !, который также преобразует тип в «boolean» .

const isTrue  = !0;
const isFalse = !1;
const alsoFalse = !!0;

Этот тип преобразования типов может быть полезен в условных выражениях, хотя единственная причина, по которой вы бы решили определить false как !1, это если бы вы играли в code golf!

5. Преобразование в String

ПРИВЕДЕНИЕ ТИПОВ

Чтобы быстро преобразовать число в строку, мы можем использовать оператор конкатенации + , за которым следует пустой набор кавычек «» .

const val = 1 + "";
console.log(val); // Result: "1"
console.log(typeof val); // Result: "string"

6. Преобразование в Number

ПРИВЕДЕНИЕ ТИПОВ

Обратное можно быстро сделать с помощью оператора сложения + .

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"

Хотя я не могу придумать много вариантов использования, но побитовый оператор NOT также можно использовать в логических значениях: ~true = -2 и ~false = -1 .

7. Быстрое возведение в степень

ОПЕРАЦИИ

Начиная с ES7 стало возможным использовать оператор возведения в степень ** как сокращение для степеней, что быстрее, чем запись Math.pow(2, 3). Это простой материал, но он попал в список, потому что не так много учебных содержит этот оператор!

console.log(2 ** 3); // Result: 8

Не следует его путать с ^ символом, обычно используемым для записи показателей степени, т.к в JavaScript он является побитовым оператором XOR.

До ES7 сокращение существовало только для степеней с основанием 2 с использованием оператора побитового сдвига влево << :

// The following expressions are equivalent:
Math.pow(2, n);
2 << (n - 1);
2**n;

Например, 2 << 3 = 16 эквивалентно 2 ** 4 = 16 .

8. Быстрое преобразование Float в Integer

ОПЕРАЦИИ / ПРИВЕДЕНИЕ ТИПОВ

Если вы хотите преобразовать число с плавающей точкой в целое число, вы можете использовать Math.floor(), Math.ceil() или Math.round(). Но есть также более быстрый способ обрезать число с плавающей точкой до целого числа, используя | оператор побитового ИЛИ.

console.log(23.9 | 0);  // Result: 23
console.log(-23.9 | 0); // Result: -23

Поведение | зависит от того, имеете ли вы дело с положительными или отрицательными числами, поэтому лучше использовать его вы точно уверены в операндах.

Если n положительно, n | 0 округляется в большую сторону. Если n отрицательное — округляется в меньшую. Чтобы выразиться точнее, эта операция удаляет все, что следует после десятичной точки, усекая число с плавающей точкой до целого числа.

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

Удалить последние цифры

Побитовый оператор ИЛИ также можно использовать для удаления любого количества цифр из конца целого числа. Это означает, что нам не нужно использовать подобный код для преобразования между типами:

let str = "1553"; 
Number(str.substring(0, str.length - 1));

Вместо этого побитовый оператор OR позволяет нам сделать так:

console.log(1553 / 10   | 0)  // Result: 155
console.log(1553 / 100  | 0)  // Result: 15
console.log(1553 / 1000 | 0)  // Result: 1

9. Автоматический биндинг в классах

КЛАССЫ

Мы можем использовать стрелочную нотацию 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>
      </>
    )
  }
};

10. Обрезание массива

МАССИВЫ

Если вы хотите удалить значения из конца массива деструктивно, есть более быстрые альтернативы, чем использование 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]

This is a particularly concise solution. However, I have found the run-time of the slice() method to be even faster. If speed is your main goal, consider using something like this:

Это особенно краткое решение. Тем не менее, я обнаружил, что время выполнения slice() метода еще быстрее. Если ваша главная цель — скорость, подумайте об этом:

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]

11. Получить n последних элементов массива

МАССИВЫ

Метод массива 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]

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

JSON

Lastly, you may have used JSON.stringify before, but did you realise it can also help indent your JSON for you?

Возможно вы использовали JSON.stringify и раньше, но знали ли вы, что можно сделать отступ для вашего JSON?

Метод stringify() принимает два дополнительных параметра: replacer function, которую вы можете использовать для фильтрации JSON, и space значение.

Значение space принимает целое число для числа пробелов или строку (например ‘\t’ для вставки табов), что может упростить вам чтение JSON.

console.log(JSON.stringify({ alpha: 'A', beta: 'B' }, null, '\t'));
   // Result:
   // '{
   //     "alpha": A,
   //     "beta": B
   // }'

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

Есть какие-то собственные трюки с JavaScript? Я хотел бы прочитать их в комментариях ниже!

 

Перевод статьи 12 JavaScript Tricks You Won’t Find in Most Tutorials.

Источник