-
28. Debounce Function (디바운스 함수)
-
29. Throttle Function (스로틀 함수)
-
30. Deep Clone Objects (깊은 복사)
-
31. Memoization (메모이제이션)
-
32. Currying Functions (커링 함수)
-
33. Partial Application (부분 적용)
-
34. Function Composition (함수 합성)
-
35. Function Pipelining (함수 파이프라이닝)
-
36. Immediately Invoked Function Expression (즉시 실행 함수 표현)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,
이 글은 5번째 중 4번째 글이다.
28. Debounce Function (디바운스 함수)
문제: 윈도우 리사이즈 이벤트와 같은 자주 호출되는 함수는 성능을 저하시킬 수 있습니다.
해결책: 디바운스 함수를 사용하여 함수가 일정 시간 동안 비활성 상태일 때만 실행되도록 하세요.
// PROBLEM: debounce 미사용
function logResize() {
console.log('Window resized');
}
window.addEventListener('resize', logResize);
// SOLUTION: debounce 사용
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
window.addEventListener('resize', debounce(() => {
console.log('Window resized');
}, 200));
29. Throttle Function (스로틀 함수)
문제: 스크롤이나 리사이즈 같은 자주 발생하는 이벤트에서 함수 실행 빈도를 제한할 필요가 있습니다.
해결책: 스로틀 함수를 사용하여 함수 실행 빈도를 제한하세요.
// PROBLEM: throttle 미사용
function logScroll() {
console.log('Window scrolled');
}
window.addEventListener('scroll', logScroll);
// SOLUTION: throttle 사용
// 함수 실행 빈도를 제한하여 성능을 향상
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function (...args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (Date.now() - lastRan >= limit) {
func.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
window.addEventListener('scroll', throttle(() => {
console.log('Window scrolled');
}, 200));
30. Deep Clone Objects (깊은 복사)
문제: 중첩된 객체를 복사하는 것은 까다롭고 오류를 일으키기 쉽습니다.
해결책: 구조적 복사 또는 Lodash와 같은 라이브러리를 사용하여 객체를 깊게 복사하세요.
// PROBLEM: 얕은 복사
// 얕은 복사를 사용하여 중첩된 객체의 참조가 공유되기 때문에 원본 객체가 변경된다.
const obj = { a: 1, b: { c: 2 } };
const shallowClone = { ...obj };
shallowClone.b.c = 3;
console.log(obj.b.c); // 3, 원본 객체가 변경됨
// SOLUTION: 깊은 복사
// 중첩된 객체를 값으로 복사하여 원본 객체의 의도하지 않은 변경을 방지하자.
const obj = { a: 1, b: { c: 2 } };
const deepClone = JSON.parse(JSON.stringify(obj));
console.log(deepClone); // { a: 1, b: { c: 2 } }
31. Memoization (메모이제이션)
문제: 반복적으로 호출되는 비용이 큰 함수는 성능을 저하시킬 수 있습니다.
해결책: 메모이제이션을 사용하여 비용이 큰 함수 호출 결과를 캐시하세요.
// PROBLEM: 메모이제이션 X
// 동일한 계산이 반복적으로 수행되어 성능 저하를 초래할 수 있다.
function expensiveFunction(num) {
console.log('Computing…');
return num * 2;
}
console.log(expensiveFunction(2)); // "Computing…" 4
console.log(expensiveFunction(2)); // "Computing…" 4, 동일한 계산이 반복됨
// SOLUTION: 메모이제이션 O
// 비용이 큰 함수 호출 결과를 캐시하여 성능을 향상시키자.
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)); // "Computing…" 4
console.log(expensiveFunction(2)); // 4
32. Currying Functions (커링 함수)
문제: 여러 매개변수를 가진 함수를 만드는 것은 번거로울 수 있습니다.
해결책: 커링을 사용하여 부분 적용된 매개변수를 가진 함수를 만드세요.
// PROBLEM: 커링 함수 X
// 함수 호출 시 모든 매개변수를 한 번에 제공해야 하므로 유연성이 떨어진다.
function sum(a, b, c) {
return a + b + c;
}
console.log(sum(1, 2, 3)); // 6
// 모든 매개변수를 한 번에 제공해야 함
// SOLUTION: 커링 함수 O
// 커링함수는 매개변수를 부분적으로 적용할 수 있는 함수를 생성하여 코드를 유연하게 만든다.
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 (부분 적용)
문제: 반복적인 인수를 가진 함수를 호출하는 것은 번거로울 수 있습니다.
해결책: 부분 적용을 사용하여 일부 인수를 미리 적용한 함수를 만드세요.
// PROBLEM: 부분 적용 X
// 함수를 호출할 때마다 모든 매개변수를 제공해야 하므로 유연성이 떨어진다.
function multiply(a, b, c) {
return a * b * c;
}
console.log(multiply(2, 3, 4)); // 24
// 매번 모든 매개변수를 제공해야 함
// SOLUTION: 부분 적용 O
// 일부 인수를 미리 적용한 새 함수를 생성하여 코드를 더 유연하고 재사용 가능하게 한다.
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. Function Composition (함수 합성)
문제: 여러 함수를 하나의 작업으로 결합하는 것은 번거로울 수 있습니다.
해결책: 함수 합성을 사용하여 여러 함수를 결합하세요.
// PROBLEM: 함수 합성 X
// 함수를 중첩 호출해야 하므로 코드가 장황해질 수 있다.
function add(x) {
return x + 1;
}
function multiply(x) {
return x * 2;
}
const result = multiply(add(5));
console.log(result); // 12
// 함수를 중첩 호출해야 함
// SOLUTION: 함수 합성 O
// 함수 합성은 여러 함수를 결합하여 모듈화되고 재사용 가능한 코드를 작성할 수 있게 한다.
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. Function Pipelining (함수 파이프라이닝)
문제: 값을 함수에 순차적으로 적용하는 것은 장황할 수 있습니다.
해결책: 함수 파이프라이닝을 사용하여 함수를 순차적으로 적용하세요.
// PROBLEM: 함수 파이프라이닝 X
// 함수를 중첩 호출해야 하므로 코드가 장황해질 수 있다.
function add(x) {
return x + 1;
}
function multiply(x) {
return x * 2;
}
const result = multiply(add(5));
console.log(result); // 12
// 함수를 중첩 호출해야 함
// SOLUTION: 함수 파이프라이닝 O
// 함수 파이프라이닝은 값을 함수에 순차적으로 적용하여 코드의 가독성과 유지보수성을 향상시킨다.
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. Immediately Invoked Function Expression (즉시 실행 함수 표현)
문제: 정의 즉시 함수를 실행하는 것은 번거로울 수 있습니다.
해결책: 즉시 실행 함수 표현식 (IIFE)을 사용하세요.
// PROBLEM: IIFE 미사용
// 함수를 별도로 호출해야 하므로 코드가 장황해질 수 있다.
function runImmediately() {
console.log('This runs immediately!');
}
runImmediately();
// SOLUTION: IIFE 사용
// IIFE는 함수를 정의하자마자 실행할 수 있어, 고립된 스코프를 생성하고 전역 네임스페이스 오염을 피하는 데 유용하다.
(function () {
console.log('This runs immediately!');
})();
36. IIFE의 경우, 자체 스코프를 지닌 모듈 시스템 ES6 등장으로 IIFE의 사용 빈도는 줄어들었다고 한다.
같이 읽으면 좋을 글
2024.06.08 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(1)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(1)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,팁이 45가지나 되는 만큼 한 글에 담기보단 9개씩 5번으로 나눠서 포스팅할 예정이다.이 글은 5번째 중 1번
juniortunar.tistory.com
2024.06.09 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 2번째 글이다. 10. Nullish Coalescing Operator ( 널리쉬 병합 연산자)문제: || 연산자를 사용할
juniortunar.tistory.com
2024.06.11 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 4번째 글이다. 28. Debounce Function (디바운스 함수)문제: 윈도우 리사이즈 이벤트와 같은 자
juniortunar.tistory.com
2024.06.12 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 5번째. 마지막 글이다.37. Avoid Global Variables (전역 변수 피하기)문제: 전역 변수는 충돌과
juniortunar.tistory.com
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,
이 글은 5번째 중 4번째 글이다.
28. Debounce Function (디바운스 함수)
문제: 윈도우 리사이즈 이벤트와 같은 자주 호출되는 함수는 성능을 저하시킬 수 있습니다.
해결책: 디바운스 함수를 사용하여 함수가 일정 시간 동안 비활성 상태일 때만 실행되도록 하세요.
// PROBLEM: debounce 미사용
function logResize() {
console.log('Window resized');
}
window.addEventListener('resize', logResize);
// SOLUTION: debounce 사용
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
window.addEventListener('resize', debounce(() => {
console.log('Window resized');
}, 200));
29. Throttle Function (스로틀 함수)
문제: 스크롤이나 리사이즈 같은 자주 발생하는 이벤트에서 함수 실행 빈도를 제한할 필요가 있습니다.
해결책: 스로틀 함수를 사용하여 함수 실행 빈도를 제한하세요.
// PROBLEM: throttle 미사용
function logScroll() {
console.log('Window scrolled');
}
window.addEventListener('scroll', logScroll);
// SOLUTION: throttle 사용
// 함수 실행 빈도를 제한하여 성능을 향상
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function (...args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (Date.now() - lastRan >= limit) {
func.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
window.addEventListener('scroll', throttle(() => {
console.log('Window scrolled');
}, 200));
30. Deep Clone Objects (깊은 복사)
문제: 중첩된 객체를 복사하는 것은 까다롭고 오류를 일으키기 쉽습니다.
해결책: 구조적 복사 또는 Lodash와 같은 라이브러리를 사용하여 객체를 깊게 복사하세요.
// PROBLEM: 얕은 복사
// 얕은 복사를 사용하여 중첩된 객체의 참조가 공유되기 때문에 원본 객체가 변경된다.
const obj = { a: 1, b: { c: 2 } };
const shallowClone = { ...obj };
shallowClone.b.c = 3;
console.log(obj.b.c); // 3, 원본 객체가 변경됨
// SOLUTION: 깊은 복사
// 중첩된 객체를 값으로 복사하여 원본 객체의 의도하지 않은 변경을 방지하자.
const obj = { a: 1, b: { c: 2 } };
const deepClone = JSON.parse(JSON.stringify(obj));
console.log(deepClone); // { a: 1, b: { c: 2 } }
31. Memoization (메모이제이션)
문제: 반복적으로 호출되는 비용이 큰 함수는 성능을 저하시킬 수 있습니다.
해결책: 메모이제이션을 사용하여 비용이 큰 함수 호출 결과를 캐시하세요.
// PROBLEM: 메모이제이션 X
// 동일한 계산이 반복적으로 수행되어 성능 저하를 초래할 수 있다.
function expensiveFunction(num) {
console.log('Computing…');
return num * 2;
}
console.log(expensiveFunction(2)); // "Computing…" 4
console.log(expensiveFunction(2)); // "Computing…" 4, 동일한 계산이 반복됨
// SOLUTION: 메모이제이션 O
// 비용이 큰 함수 호출 결과를 캐시하여 성능을 향상시키자.
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)); // "Computing…" 4
console.log(expensiveFunction(2)); // 4
32. Currying Functions (커링 함수)
문제: 여러 매개변수를 가진 함수를 만드는 것은 번거로울 수 있습니다.
해결책: 커링을 사용하여 부분 적용된 매개변수를 가진 함수를 만드세요.
// PROBLEM: 커링 함수 X
// 함수 호출 시 모든 매개변수를 한 번에 제공해야 하므로 유연성이 떨어진다.
function sum(a, b, c) {
return a + b + c;
}
console.log(sum(1, 2, 3)); // 6
// 모든 매개변수를 한 번에 제공해야 함
// SOLUTION: 커링 함수 O
// 커링함수는 매개변수를 부분적으로 적용할 수 있는 함수를 생성하여 코드를 유연하게 만든다.
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 (부분 적용)
문제: 반복적인 인수를 가진 함수를 호출하는 것은 번거로울 수 있습니다.
해결책: 부분 적용을 사용하여 일부 인수를 미리 적용한 함수를 만드세요.
// PROBLEM: 부분 적용 X
// 함수를 호출할 때마다 모든 매개변수를 제공해야 하므로 유연성이 떨어진다.
function multiply(a, b, c) {
return a * b * c;
}
console.log(multiply(2, 3, 4)); // 24
// 매번 모든 매개변수를 제공해야 함
// SOLUTION: 부분 적용 O
// 일부 인수를 미리 적용한 새 함수를 생성하여 코드를 더 유연하고 재사용 가능하게 한다.
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. Function Composition (함수 합성)
문제: 여러 함수를 하나의 작업으로 결합하는 것은 번거로울 수 있습니다.
해결책: 함수 합성을 사용하여 여러 함수를 결합하세요.
// PROBLEM: 함수 합성 X
// 함수를 중첩 호출해야 하므로 코드가 장황해질 수 있다.
function add(x) {
return x + 1;
}
function multiply(x) {
return x * 2;
}
const result = multiply(add(5));
console.log(result); // 12
// 함수를 중첩 호출해야 함
// SOLUTION: 함수 합성 O
// 함수 합성은 여러 함수를 결합하여 모듈화되고 재사용 가능한 코드를 작성할 수 있게 한다.
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. Function Pipelining (함수 파이프라이닝)
문제: 값을 함수에 순차적으로 적용하는 것은 장황할 수 있습니다.
해결책: 함수 파이프라이닝을 사용하여 함수를 순차적으로 적용하세요.
// PROBLEM: 함수 파이프라이닝 X
// 함수를 중첩 호출해야 하므로 코드가 장황해질 수 있다.
function add(x) {
return x + 1;
}
function multiply(x) {
return x * 2;
}
const result = multiply(add(5));
console.log(result); // 12
// 함수를 중첩 호출해야 함
// SOLUTION: 함수 파이프라이닝 O
// 함수 파이프라이닝은 값을 함수에 순차적으로 적용하여 코드의 가독성과 유지보수성을 향상시킨다.
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. Immediately Invoked Function Expression (즉시 실행 함수 표현)
문제: 정의 즉시 함수를 실행하는 것은 번거로울 수 있습니다.
해결책: 즉시 실행 함수 표현식 (IIFE)을 사용하세요.
// PROBLEM: IIFE 미사용
// 함수를 별도로 호출해야 하므로 코드가 장황해질 수 있다.
function runImmediately() {
console.log('This runs immediately!');
}
runImmediately();
// SOLUTION: IIFE 사용
// IIFE는 함수를 정의하자마자 실행할 수 있어, 고립된 스코프를 생성하고 전역 네임스페이스 오염을 피하는 데 유용하다.
(function () {
console.log('This runs immediately!');
})();
36. IIFE의 경우, 자체 스코프를 지닌 모듈 시스템 ES6 등장으로 IIFE의 사용 빈도는 줄어들었다고 한다.
같이 읽으면 좋을 글
2024.06.08 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(1)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(1)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,팁이 45가지나 되는 만큼 한 글에 담기보단 9개씩 5번으로 나눠서 포스팅할 예정이다.이 글은 5번째 중 1번
juniortunar.tistory.com
2024.06.09 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 2번째 글이다. 10. Nullish Coalescing Operator ( 널리쉬 병합 연산자)문제: || 연산자를 사용할
juniortunar.tistory.com
2024.06.11 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 4번째 글이다. 28. Debounce Function (디바운스 함수)문제: 윈도우 리사이즈 이벤트와 같은 자
juniortunar.tistory.com
2024.06.12 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 5번째. 마지막 글이다.37. Avoid Global Variables (전역 변수 피하기)문제: 전역 변수는 충돌과
juniortunar.tistory.com