12 прийомів роботи з JavaScript, яких немає в більшості туторіалів

12 прийомів роботи з JavaScript, яких немає в більшості туторіалів

Коли я почав вивчати JavaScript, то насамперед склав список прийомів, які допомагали мені заощаджувати час. Я підглянув їх у інших програмістів, на різних сайтах та у мануалах.

У цій статті я покажу 12 відмінних способів покращити та прискорити свій JavaScript-код. Найчастіше вони універсальні.

Нагадуємо: для всіх читачів "Хабра" - знижка 10 000 рублів при записі на будь-який курс Skillbox за промокодом "Хабр".

Skillbox рекомендує: Практичний курс «Мобільний розробник PRO».

Фільтрування унікальних значень

МАСИВИ

Тип об'єкта Set був введений в ES6, разом із …, spread-оператором, ми можемо використовувати його для створення нового масиву, в якому містяться лише унікальні значення.

const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [...new Set(array)];
 
console.log(uniqueArray); // Result: [1, 2, 3, 5]

У звичайній ситуації для виконання тієї ж операції потрібно набагато більше коду.

Цей прийом працює для масивів, що містять примітивні типи: undefined, null, boolean, string та number. Якщо ви працюєте з масивом, який містить об'єкти, функції або додаткові масиви, вам знадобиться інший підхід.

Довжина кеш-масиву в циклах

ЦИКЛИ

Коли ви вивчаєте for для циклів, слідуйте стандартній процедурі:

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

Тим не менш, при такому синтаксисі цикл повторно перевіряє довжину масиву при кожній ітерації.

Іноді це може бути корисно, але в більшості випадків ефективніше кешувати довжину масиву, що вимагатиме одного звернення до нього. Ми можемо зробити це шляхом визначення змінної довжини, де задати змінну i, наприклад, так:

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

У принципі, майже те саме, що й вище, але при збільшенні розміру циклу ми отримаємо значну економію часу.

Оцінка короткого замикання (оцінка Маккарті)

УМОВНІ ОПЕРАТОРИ

Тернарний оператор – швидкий та ефективний спосіб написати прості (а іноді й не дуже прості) conditional statements:

х> 100? "більше 100": "менше 100";
х> 100? (x> 200? "більше 200": "між 100-200"): "менше 100";

Але іноді навіть тернарний оператор складніше, ніж потрібно. Замість нього ми можемо використовувати 'and' && та 'or' || логічні оператори з метою оцінки деяких виразів ще коротшим способом. Його часто називають "коротким замиканням" або "оцінкою короткого замикання".

Як це працює

Скажімо, ми хочемо повернути лише одну з двох чи більше умов.

Використання && поверне перше значення false. Якщо кожен операнд оцінюється як true, то буде повернуто останній обчислений вираз.

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

Використання | дозволить повернути перше значення true. Якщо кожен операнд оцінюється як 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, то вона і буде повернена. В іншому випадку ми отримаємо 0.

Приклад 2

Чи були у вас проблеми з доступом до вкладеного об'єкта? Ви можете не знати, чи існує об'єкт або одне з його під властивостей, і це може призвести до проблем.

Наприклад, ми хотіли отримати доступ до якості data в this.state, але data не визначено, поки наша програма не поверне запит на вибірку.

Залежно від того, де ми його використовуємо, виклик this.state.data може перешкодити запуску програми. Щоб вирішити проблему, ми могли б обернути це на умовний вираз:

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

Найкращим варіантом буде використання оператора «or».

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

Ми не можемо змінити код вище, щоб використовувати &&. Оператор 'Fetching Data' && this.state.data поверне this.state.data незалежно від того, є він undefined чи ні.

Опціональний ланцюжок

Можна запропонувати використовувати опціональний ланцюжок при спробі повернути властивість глибоко в деревоподібну структуру. Так, знак питання? може використовуватися для отримання властивості, тільки якщо воно не дорівнює нулю (null).

Наприклад, ми могли б виконати рефакторинг прикладу вище, отримавши this.state.data?.. (). Тобто data повертається лише тому випадку, якщо значення не null.

Або якщо важливо, чи визначено state чи ні, ми могли б повернути this.state?.data.

Перетворення на Boolean

ПЕРЕТВОРЕННЯ ТИПІВ

Крім звичайних логічних функцій true та false, JavaScript також розглядає всі інші значення як truthy чи falsy.

Поки не вказано інше, всі значення JavaScript - truthy, за винятком 0, «», null, undefined, NaN і, звичайно, false. Останні є falsy.

Ми можемо легко перемикатися між тими та іншими, використовуючи оператор !, який також перетворює тип на логічний.

const isTrue  = !0;
const isFalse = !1;
const alsoFalse = !!0;
 
console.log(true); // Result: true
console.log(typeof true); // Result: "boolean"

Перетворення на рядок

ПЕРЕТВОРЕННЯ ТИПІВ

Швидке перетворення цілого числа в рядок можна виконати в такий спосіб.

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

Перетворення на ціле число

ПЕРЕТВОРЕННЯ ТИПІВ

Зворотне перетворення виконуємо так.

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"

<Quick Powers

ОПЕРАЦІЇ

Починаючи з ES7, можна використовувати оператор зведення у ступінь ** як скорочення для ступенів. Це набагато швидше, ніж використання Math.pow (2, 3). Начебто просто, але до списку прийомів цей момент включений, оскільки далеко не скрізь згадується.

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

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

До ES7 скорочення ** можна було застосовувати тільки для ступенів з основою 2 з використанням оператора побитового зсуву вліво.

Math.pow(2, n);
2 << (n - 1);
2**n;

Наприклад, 2 << 3 = 16 еквівалентно виразу 2 ** 4 = 16.

Float у ціле число

ОПЕРАЦІЇ / ПЕРЕТВОРЕННЯ ТИПІВ

При необхідності перетворити float на ціле число можна скористатися Math.floor(), Math.ceil() або Math.round(). Але є й швидший шлях, цього використовуємо |, тобто оператор OR.

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

Поведінка | значною мірою залежить від того, чи маєте ви справу з позитивними чи негативними числами, тому цей спосіб підходить лише в тому випадку, якщо ви впевнені, що робите.

n | 0 видаляє все, що йде після десяткового роздільника, урізаючи число з плаваючою точкою до цілого числа.

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

Забираємо замикаючі числа

Оператор OR можна використовувати для того, щоб усунути будь-яку кількість цифр з числа. Це означає, що нам не потрібно перетворювати типи, як тут:

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

Натомість просто прописуємо:

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

Автоматичне зв'язування

КЛАСИ

Стрільні позначення 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>
      </>
    )
  }
};

Обрізка масиву

МАСИВИ

Якщо вам необхідно усунути значення з масиву, тобто більш швидкі методи, ніж 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]

Але є ще один метод, причому швидший. Якщо для вас має значення саме швидкість, то наш вибір:

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]

Виведення останнього значення (значень) масиву

МАСИВИ
Цей прийом вимагає використання методу 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]

Форматування JSON-коду

JSON

Можливо, ви вже використали JSON.stringify. Чи знаєте ви, що він допомагає форматувати ваш JSON?

Метод stringify () приймає два необов'язкові параметри: функцію replacer, яку можна використовувати для фільтрації JSON, і значення space.

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

Ось і все, сподіваюся, що всі ці прийоми були корисні. А які хитрощі ви знаєте? Напишіть їх у коментарях.

Skillbox рекомендує:

Джерело: habr.com

Додати коментар або відгук