DevGang
Авторизоваться

10 продвинутых трюков JavaScript, о которых вы не знаете

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

1. Деструктуризация с помощью сглаживания

Деструктуризация позволяет распаковывать значения из массивов или свойства объектов в отдельные переменные. Алиасинг позволяет переименовывать переменные во время этого процесса, что особенно полезно при работе с данными из внешних источников, например API.

Пример использования: При получении данных из API вы хотите дать свойствам более осмысленные имена для улучшения читаемости и удобства сопровождения кода.

const apiResponse = { first_name: 'John', user_age: 30, address: { city: 'New York', zip: '10001' } };
const { first_name: firstName, user_age: age, address: { city: hometown, zip: postalCode } } = apiResponse;
console.log(firstName); // John
console.log(age); // 30
console.log(hometown); // New York
console.log(postalCode); // 10001

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

2. Каррирование

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

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

const applyDiscount = (discount) => (price) => price - (price * discount / 100);
const tenPercentOff = applyDiscount(10);
const twentyPercentOff = applyDiscount(20);

console.log(tenPercentOff(100)); // 90
console.log(twentyPercentOff(100)); // 80

const applyTax = (taxRate) => (price) => price + (price * taxRate / 100);
const applyTenPercentTax = applyTax(10);

console.log(applyTenPercentTax(100)); // 110
console.log(applyTenPercentTax(twentyPercentOff(100))); // 88

Зачем это нужно: Оно позволяет задавать аргументы в функциях, что приводит к созданию более модульного и композитного кода. Это может значительно упростить создание многократно используемых служебных функций, делая вашу кодовую базу чище и проще в обслуживании. Каррирование особенно полезно в сценариях, где функции должны быть частично применены или повторно использованы с различными конфигурациями.

3. Дебаунсинг и дросселирование

Дебаунсинг и дросселирование – это техники, позволяющие контролировать частоту выполнения функции. Они особенно полезны для оптимизации обработчиков событий, чтобы предотвратить чрезмерные вызовы функций, которые могут снизить производительность.

Дебаунсинг

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

Пример использования: Оптимизация поля ввода поиска для уменьшения количества вызовов API. Это позволяет предотвратить перегрузку сервера и улучшить пользовательский опыт благодаря тому, что поиск начинается только после того, как пользователь закончил вводить текст.

function debounce(func, delay) {
  let timeoutId;
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

const search = debounce((query) => {
  console.log(`Searching for ${query}`);
  // Imagine an API call here
}, 300);

document.getElementById('searchInput').addEventListener('input', (event) => {
  search(event.target.value);
});

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

Дросселирование

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

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

function throttle(func, interval) {
  let lastCall = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= interval) {
      lastCall = now;
      func.apply(this, args);
    }
  };
}

const handleScroll = throttle(() => {
  console.log('Scrolled');
  // Imagine complex calculations or DOM updates here
}, 300);

window.addEventListener('scroll', handleScroll);

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

4. Мемоизация

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

Пример использования: повышение производительности рекурсивных функций, таких как вычисление Фибоначчи. Без мемоизации каждый вызов функции Фибоначчи мог бы избыточно вычислять одни и те же значения несколько раз, что привело бы к экспоненциальной временной сложности.

const memoize = (fn) => {
  const cache = {};
  return (...args) => {
    const key = JSON.stringify(args);
    if (!cache[key]) {
      cache[key] = fn(...args);
    }
    return cache[key];
  };
};

const fibonacci = memoize((n) => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

console.log(fibonacci(40)); // 102334155

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

5. Прокси

Объект прокси позволяет создавать прокси для другого объекта, что дает возможность перехватывать и переопределять фундаментальные операции, такие как поиск свойств, присваивание, перечисление, вызов функций и т. д. Это обеспечивает мощный способ добавления пользовательского поведения к объектам.

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

const user = {
  name: 'John',
  age: 30
};

const handler = {
  get: (target, prop) => {
    console.log(`Getting ${prop}`);
    return target[prop];
  },
  set: (target, prop, value) => {
    if (prop === 'age' && typeof value !== 'number') {
      throw new TypeError('Age must be a number');
    }
    console.log(`Setting ${prop} to ${value}`);
    target[prop] = value;
    return true;
  }
};

const proxyUser = new Proxy(user, handler);
console.log(proxyUser.name); // Getting name, John
proxyUser.age = 35; // Setting age to 35
// proxyUser.age = '35'; // Throws TypeError

Зачем это нужно: Позволяет настраивать поведение операций с объектами, таких как проверка, ведение журнала и т. д., улучшая контроль над манипуляциями с объектами. Прокси также можно использовать для реализации сложной логики, такой как управление доступом и привязка данных. Это делает их универсальным инструментом для управления и расширения поведения объектов.

6. Генераторы

Генераторы – это функции, из которых можно выйти, а затем снова войти, сохраняя их контекст и привязки переменных при повторных входах. Они полезны для реализации итераторов и синхронной обработки асинхронных задач.

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

function* objectEntries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

const user = { name: 'John', age: 30, city: 'New York' };

for (let [key, value] of objectEntries(user)) {
  console.log(`${key}: ${value}`);
}
// name: John
// age: 30
// city: New York

Зачем это нужно: Предоставляет мощный инструмент для реализации пользовательских итераторов и упрощения асинхронных рабочих процессов. Генераторы облегчают работу со сложной логикой итераций и асинхронными процессами, что приводит к созданию более читабельного и удобного кода. Их также можно использовать для решения таких задач, как управление асинхронными операциями более простым и линейным способом с помощью таких библиотек, как co.

7. Правильное использование консоли

Пример использования: Улучшение протоколирования для отладки сложных объектов. Консольные методы, такие как console.table, console.group и console.time, могут предоставить более структурированную и информативную отладочную информацию.

// Basic logging
console.log('Simple log');
console.error('This is an error');
console.warn('This is a warning');

// Logging tabular data
const users = [
  { name: 'John', age: 30, city: 'New York' },
  { name: 'Jane', age: 25, city: 'San Francisco' },
];
console.table(users);

// Grouping logs
console.group('User Details');
console.log('User 1: John');
console.log('User 2: Jane');
console.groupEnd();

// Timing code execution
console.time('Timer');
for (let i = 0; i < 1000000; i++) {
  // Some heavy computation
}
console.timeEnd('Timer');

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

8. Структурированное клонирование с помощью structuredClone

Глубокое клонирование объектов с помощью новой функции structuredClone. В отличие от традиционного неглубокого копирования, структурированное клонирование создает глубокую копию объекта, гарантируя, что вложенные объекты также будут скопированы. Этот метод позволяет избежать ограничений JSON.parse(JSON.stringify(obj)), который не может обрабатывать некоторые типы данных, такие как функции, неопределенные (undefined) и круговые ссылки.

Пример использования: Создание глубокой копии сложных объектов. Это полезно, когда вам нужно дублировать объекты для операций, которые не должны изменять исходные данные.

const obj = { 
  a: 1, 
  b: { c: 2 },
  date: new Date(),
  arr: [1, 2, 3],
  nestedArr: [{ d: 4 }]
};
const clonedObj = structuredClone(obj);

console.log(clonedObj); 
// { a: 1, b: { c: 2 }, date: 2023-06-08T00:00:00.000Z, arr: [1, 2, 3], nestedArr: [{ d: 4 }] }
console.log(clonedObj === obj); // false
console.log(clonedObj.b === obj.b); // false
console.log(clonedObj.date === obj.date); // false
console.log(clonedObj.arr === obj.arr); // false
console.log(clonedObj.nestedArr[0] === obj.nestedArr[0]); // false

Зачем это нужно: Предоставляет встроенный эффективный способ глубокого клонирования объектов, позволяющий избежать подводных камней и сложностей, связанных с ручным выполнением глубокого копирования. Этот метод более надежен и лучше справляется со сложными структурами данных, чем такие альтернативы, как JSON.parse(JSON.stringify(obj)).

9. Самовызывающиеся функции

Самовызывающиеся функции, также известные как Immediately Invoked Function Expressions (IIFE), выполняются автоматически после их создания. Они полезны для инкапсуляции кода, чтобы избежать загрязнения глобальной области видимости, что очень важно для поддержания чистого и модульного кода.

Пример использования: инкапсуляция кода, чтобы избежать загрязнения глобальной области видимости. Эта техника особенно полезна в старых средах JavaScript, где недоступна область видимости блоков (let и const), или в сценариях, где требуется немедленное выполнение логики инициализации.

(function() {
  const privateVar = 'This is private';
  console.log('Self-invoking function runs immediately');
  // Initialization code here
})();

// Private variables are not accessible from outside
// console.log(privateVar); // ReferenceError: privateVar is not defined

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

10. Буквенные обозначения шаблонов

Буквенные обозначения шаблонов позволяют настраивать способ обработки буквенных обозначений шаблонов. Они полезны для создания специализированных шаблонов, например для интернационализации, дезинфекции HTML или генерации динамических SQL-запросов.

Пример использования: санирование пользовательского ввода в HTML-шаблонах для предотвращения XSS-атак. Эта техника гарантирует, что пользовательский контент будет безопасно вставлен в DOM без выполнения вредоносных скриптов.

function sanitize(strings, ...values) {
  return strings.reduce((result, string, i) => {
    let value = values[i - 1];
    if (typeof value === 'string') {
      value = value.replace(/&/g, '&amp;')
                   .replace(/</g, '&lt;')
                   .replace(/>/g, '&gt;')
                   .replace(/"/g, '&quot;')
                   .replace(/'/g, '&#39;');
    }
    return result + value + string;
  });
}

const userInput = '<script>alert("xss")</script>';
const message = sanitize`User input: ${userInput}`;
console.log(message); // User input: &lt;script&gt;alert("xss")&lt;/script&gt;

Зачем это нужно: Предоставляет мощный механизм для контроля и настройки отображения буквенных выражений шаблонов, обеспечивая более безопасное и гибкое создание шаблонов. Метки шаблонов могут использоваться для обеспечения безопасности, форматирования строк и создания динамического содержимого, повышая надежность и универсальность вашего кода.

Заключение

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

Источник доступен по ссылке.

#JavaScript #Подборка
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу