Лучшие хаки JavaScript: От новичка до гуру кода (Завершение)
Продолжаем делиться секретами чистого кода в JavaScript!
Если вы уже знакомы с нашими предыдущими статьями, вы наверняка знаете множество полезных приемов.
Но даже если вы пропустили часть материалов, не отчаивайтесь! Вы всегда можете наверстать упущенное.
Мы рекомендуем вам ознакомиться с нашими статьями Начало и Продолжение по ссылке — в них вы найдете много ценной информации.
31 Мемоизация
Кэширование результатов вызовов функций с помощью мемоизации может значительно ускорить работу, особенно для дорогих вычислений.
function memoize(func) {
const cache = new Map();
return function (…args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = func.apply(this, args);
cache.set(key, result);
return result;
};
}
const expensiveFunction = memoize((num) => {
console.log('Computing…');
return num * 2;
});
console.log(expensiveFunction(2)); // "Comput
ing…" 4
console.log(expensiveFunction(2)); // 4
Хотите узнать подробнее о замыканиях JavaScript? Здесь предоставлена информация о понимании закрытых переменных, обратных вызовов и мемоизации для эффективного кода.
32 Каррирование функций
Используйте каррирование для создания функций с частично примененными параметрами, а также частичное применение, чтобы предварительно задать часть аргументов функции.
function curry(func) {
return function curried(…args) {
if (args.length >= func.length) {
return func.apply(this, args);
}
return function (…nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
};
}
const sum = (a, b, c) => a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6
33 Частичное применение (Partial Application)
Часто бывает нужно вызывать функцию с одинаковыми аргументами. Частичное применение позволяет предварительно задать часть аргументов, делая код более лаконичным.
function partial(func, …presetArgs) {
return function (…laterArgs) {
return func(…presetArgs, …laterArgs);
};
}
const multiply = (a, b, c) => a * b * c;
const double = partial(multiply, 2);
console.log(double(3, 4)); // 24
34 Композиция функций
Объединяйте несколько функций в одну операцию, используя композицию функций. Это повышает читаемость кода и делает его более структурированным.
const compose = (…funcs) => (arg) =>
funcs.reduceRight((prev, fn) => fn(prev), arg);
const add = (x) => x + 1;
const multiply = (x) => x * 2;
const addThenMultiply = compose(multiply, add);
console.log(addThenMultiply(5)); // 12
35 Конвейеризация функций
Последовательно применяйте ряд функций к значению, используя конвейеризацию. Это позволяет организовать сложные операции в цепочку.
const pipe = (…funcs) => (arg) =>
funcs.reduce((prev, fn) => fn(prev), arg);
const add = (x) => x + 1;
const multiply = (x) => x * 2;
const addThenMultiply = pipe(add, multiply);
console.log(addThenMultiply(5)); // 12
Углубитесь в два мощных инструмента функционального программирования: каррирование и конвейеризацию. Разберите их отличия, просмотрите примеры использования и попробуйте понять, какой подход лучше всего подходит для ваших задач.
36 Самовызывающиеся функции
Выполняйте функцию сразу после ее определения, используя IIFE. Это позволяет избежать проблем с областью видимости и созданием глобальных переменных.
(function () {
console.log('This runs immediately!');
})();
IIFE (Immediately Invoked Function Expression) выполняет функцию сразу после определения. Полезно для создания изолированных областей и предотвращения загрязнения глобального пространства имен.
37 Избегайте глобальных переменных
Избегайте загрязнения глобального пространства имен, используя локальные переменные и модули. Это защищает от конфликтов и непреднамеренных побочных эффектов.
// Using local variables
function doSomething() {
let localVariable = 'This is local';
console.log(localVariable);
}
// Using modules
const myModule = (function () {
let privateVariable = 'This is private';
return {
publicMethod() {
console.log(privateVariable);
},
};
})();
myModule.publicMethod(); // "This is private"
Предотвращает конфликты и непреднамеренные побочные эффекты. Делает код более модульным и удобным для поддержки.
38 Инкапсуляция
Используйте замыкания для скрытия внутренних деталей функции и предотвращения неправильного использования. Это повышает безопасность и делает код более структурированным.
function createCounter() {
let count = 0;
return {
increment() {
count++;
return count;
},
decrement() {
count - ;
return count;
},
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
Инкапсулируют внутренние данные и предоставляют только необходимую функциональность. Повышает безопасность кода и удобство его обслуживания.
39 Паттерн Module
Организуйте код в повторно используемые модули, используя шаблон модуля. Это делает код более структурированным и позволяет легко повторно использовать отдельные компоненты.
const myModule = (function () {
let privateVariable = 'This is private';
function privateMethod() {
console.log(privateVariable);
}
return {
publicMethod() {
privateMethod();
},
};
})();
myModule.publicMethod(); // "This is private"
На примере кода шаблон Module создает повторно используемый и инкапсулированный код, улучшая организацию и удобство поддержки.
40 Паттерн Singleton
Шаблон модуля позволяет создавать повторно используемый и инкапсулированный код, а шаблон singleton - создавать только один экземпляр класса.
const singleton = (function () {
let instance;
function createInstance() {
return {
name: 'Singleton Instance',
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
},
};
})();
const instance1 = singleton.getInstance();
const instance2 = singleton.getInstance();
console.log(instance1 === instance2); // true
Гарантирует создание только одного экземпляра класса. Полезно для управления общими ресурсами или конфигурациями.
41 Паттерн Factory (Фабричный метод)
Используйте шаблон фабрики для упрощения создания объектов со сложной инициализацией.
function createUser(name, role) {
return {
name,
role,
sayHello() {
console.log(`Hello, my name is ${this.name} and I am a ${this.role}`);
},
};
}
const admin = createUser('Alice', 'admin');
const user = createUser('Bob', 'user');
admin.sayHello(); // "Hello, my name is Alice and I am an admin"
user.sayHello(); // "Hello, my name is Bob and I am a user"
На данном примере можно увидеть создание объектов со сложной инициализацией гибким и многоразовым способом.
42 Паттерн Observer
Шаблон наблюдателя помогает управлять изменениями состояния и уведомлять заинтересованные компоненты.
function Subject() {
this.observers = [];
}
Subject.prototype = {
subscribe(observer) {
this.observers.push(observer);
},
unsubscribe(observer) {
this.observers = this.observers.filter((obs) => obs !== observer);
},
notify(data) {
this.observers.forEach((observer) => observer.update(data));
},
};
function Observer(name) {
this.name = name;
}
Observer.prototype.update = function (data) {
console.log(`${this.name} received data: ${data}`);
};
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.notify('New data available'); // "Observer 1 received data: New data available" "Observer 2 received data: New data available"
Шаблон наблюдателя позволяет управлять изменениями состояния и уведомляет нескольких наблюдателей, улучшая организацию и удобство обслуживания кода.
43 Делегирование событий
Делегирование событий позволяет эффективно управлять событиями, избегая излишнего добавления прослушивателей к каждому элементу.
document.getElementById('parent').addEventListener('click', (event) => {
if (event.target && event.target.matches('button.className')) {
console.log('Button clicked:', event.target.textContent);
}
});
Эффективное управление событиями, добавляя один прослушиватель событий к общему родительскому элементу и обрабатывая события для нескольких дочерних элементов.
44 Избегайте использования eval()
Избегайте использования eval()
, так как оно может представлять угрозу безопасности и снижать производительность.
// Avoid
const code = 'console.log("Hello, world!")';
eval(code); // "Hello, world!"
// Use safer alternatives
const func = new Function('console.log("Hello, world!")');
func(); // "Hello, world!"
Отказ от eval()
предотвращает уязвимости безопасности и проблемы с производительностью, делая код более безопасным и эффективным.
45. Использование for…of для итерации
Используйте for...of
для итерации по массивам и другим итерируемым объектам, чтобы избежать ошибок, свойственных for...in.
const arr = [1, 2, 3, 4, 5];
for (const value of arr) {
console.log(value);
}
// 1
// 2
// 3
// 4
// 5
Цикл for...of
обеспечивает простой и безопасный способ итерации по массивам и другим итерируемым объектам.
Погрузитесь в мир JavaScript-циклов: for, forEach, for...in, for...of — выбирайте свой стиль!
Прощаемся с вами, но не прощаемся с интересными статьями!
Вот и подошло к концу наше увлекательное путешествие по популярным приемам программирования.
Надеемся, вы получили заряд вдохновения и новые знания, которые помогут вам создавать потрясающие проекты!
Следите за обновлениями в нашем блоге, мы подготовили для вас еще много интересных материалов. До новых встреч!
Источник: https://medium.com/@codewithashutosh/45-javascript-super-hacks-every-developer-should-know-5f1ee3c1d380