[2026] JavaScript 함수 | 함수 선언, 화살표 함수, 콜백, 클로저 완벽 정리
이 글의 핵심
JavaScript 함수: 함수 선언, 화살표 함수, 콜백, 클로저 함수 정의 방법·매개변수와 반환값.
들어가며
함수란?
함수(Function)는 특정 작업을 묶어 이름 붙인 코드 블록입니다. JavaScript에서는 함수가 일급 객체(First-class Object)이므로, 변수에 담거나 인자로 넘기는 것이 자연스럽습니다. 이어서 설명하는 클로저는 함수가 외부 변수를 배낭처럼 들고 다니며 기억하는 개념과 연결됩니다.
실무에서 마주한 현실
개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.
1. 함수 정의 방법
함수 선언문 (Function Declaration)
아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function add(a, b) {
return a + b;
}
console.log(add(10, 20)); // 30
// 호이스팅됨 (선언 전 호출 가능)
greet(); // 안녕하세요!
function greet() {
console.log("안녕하세요!");
}
함수 표현식 (Function Expression)
다음은 javascript를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 익명 함수
const subtract = function(a, b) {
return a - b;
};
console.log(subtract(20, 10)); // 10
// 기명 함수 표현식
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1); // 재귀 시 이름 사용
};
console.log(factorial(5)); // 120
// 호이스팅 안 됨
// multiply(5, 6); // ReferenceError
const multiply = function(a, b) {
return a * b;
};
화살표 함수 (Arrow Function, ES6+)
ES6에서 도입된 간결한 함수 문법입니다: 다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 기본 형태: 여러 줄일 때
const add = (a, b) => {
// 중괄호 {}가 있으면 return 키워드 필요
return a + b;
};
// 단일 표현식: return과 중괄호 생략 가능
const add = (a, b) => a + b;
// 표현식의 결과가 자동으로 반환됨
// 매개변수 1개: 괄호 생략 가능
const square = x => x * x;
console.log(square(5)); // 25
// (x) => x * x 와 동일
// 매개변수 없음: 빈 괄호 필수
const greet = () => console.log("Hello!");
greet(); // Hello!
// 객체 반환: 괄호로 감싸기 (중요!)
const makePerson = (name, age) => ({ name, age });
// 중괄호 {}는 코드 블록으로 인식되므로
// 객체 리터럴을 반환하려면 ()로 감싸야 함
console.log(makePerson("홍길동", 25)); // { name: '홍길동', age: 25 }
// 잘못된 예:
// const makePerson = (name, age) => { name, age }; // undefined 반환!
// 여러 줄: 중괄호와 return 필요
const complexFunc = (a, b) => {
const sum = a + b;
const product = a * b;
return { sum, product };
};
화살표 함수의 특징:
- 간결한 문법: 코드가 짧고 읽기 쉬움
- this 바인딩: 렉시컬 스코프 (상위 스코프의 this 사용)
- arguments 없음: 나머지 매개변수(
...args) 사용 - 생성자 불가:
new키워드로 호출 불가 언제 사용하나:
- 콜백 함수 (배열 메서드, 이벤트 핸들러)
- 간단한 유틸리티 함수
- this 바인딩이 필요 없는 경우
함수 선언문 vs 표현식 vs 화살표 함수
| 특징 | 선언문 | 표현식 | 화살표 함수 |
|---|---|---|---|
| 호이스팅 | ✅ | ❌ | ❌ |
| this 바인딩 | 동적 | 동적 | 렉시컬 |
| arguments | ✅ | ✅ | ❌ |
| 생성자 | ✅ | ✅ | ❌ |
| 간결성 | 보통 | 보통 | 높음 |
2. 매개변수와 반환값
기본 매개변수 (Default Parameters)
아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function greet(name = "손님") {
return `안녕하세요, ${name}님!`;
}
console.log(greet("홍길동")); // 안녕하세요, 홍길동님!
console.log(greet()); // 안녕하세요, 손님님!
// 표현식도 가능
function createArray(length = 10, fill = 0) {
return Array(length).fill(fill);
}
console.log(createArray(5, 1)); // [1, 1, 1, 1, 1]
console.log(createArray(3)); // [0, 0, 0]
나머지 매개변수 (Rest Parameters)
아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
// 일반 매개변수와 함께 사용
function introduce(greeting, ...names) {
return `${greeting}, ${names.join(", ")}!`;
}
console.log(introduce("안녕하세요", "홍길동", "김철수", "이영희"));
// 안녕하세요, 홍길동, 김철수, 이영희!
구조 분해 매개변수 (Destructuring)
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 객체 구조 분해
function printUser({ name, age, city = "서울" }) {
console.log(`${name} (${age}세, ${city})`);
}
printUser({ name: "홍길동", age: 25 });
// 홍길동 (25세, 서울)
// 배열 구조 분해
function getMinMax([first, ...rest]) {
return {
min: Math.min(first, ...rest),
max: Math.max(first, ...rest)
};
}
console.log(getMinMax([3, 1, 4, 1, 5]));
// { min: 1, max: 5 }
여러 값 반환
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 배열로 반환
function getCoordinates() {
return [10, 20];
}
const [x, y] = getCoordinates();
console.log(x, y); // 10 20
// 객체로 반환 (권장)
function getUserInfo() {
return {
name: "홍길동",
age: 25,
city: "서울"
};
}
const { name, age } = getUserInfo();
console.log(name, age); // 홍길동 25
3. 고차 함수 (Higher-Order Function)
함수를 인자로 받기
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
repeat(3, console.log);
// 0
// 1
// 2
repeat(3, i => console.log(`${i}번째`));
// 0번째
// 1번째
// 2번째
함수를 반환하기
아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function makeMultiplier(factor) {
return function(x) {
return x * factor;
};
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
// 화살표 함수 버전
const makeMultiplier = factor => x => x * factor;
배열 고차 함수
다음은 javascript를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const numbers = [1, 2, 3, 4, 5];
// map: 변환
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter: 필터링
const evens = numbers.filter(x => x % 2 === 0);
console.log(evens); // [2, 4]
// reduce: 누적
const sum = numbers.reduce((acc, x) => acc + x, 0);
console.log(sum); // 15
// 체이닝
const result = numbers
.filter(x => x % 2 === 0) // [2, 4]
.map(x => x * 2) // [4, 8]
.reduce((acc, x) => acc + x, 0); // 12
console.log(result); // 12
4. 클로저 (Closure)
클로저란?
클로저(Closure)는 함수가 자신이 만들어진 환경의 변수를 붙잡고, 바깥에서 호출해도 그 값을 잃지 않는 닫힌 관계입니다.
비유(배낭): 바깥 함수가 배낭을 메고 있고, 안쪽 함수가 그 안의 물건(외부 변수)을 계속 꺼내 쓰는 형태라고 보시면 됩니다. makeCounter가 끝나도 count는 반환된 함수에 묶여 남습니다.
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function makeCounter() {
let count = 0; // 외부 함수의 변수
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// 독립적인 카운터
const counter2 = makeCounter();
console.log(counter2()); // 1
클로저 활용: 프라이빗 변수
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function createBankAccount(initialBalance) {
let balance = initialBalance; // private 변수
return {
deposit(amount) {
if (amount > 0) {
balance += amount;
return balance;
}
},
withdraw(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return balance;
}
return null;
},
getBalance() {
return balance;
}
};
}
const account = createBankAccount(10000);
console.log(account.getBalance()); // 10000
account.deposit(5000);
console.log(account.getBalance()); // 15000
account.withdraw(3000);
console.log(account.getBalance()); // 12000
// balance에 직접 접근 불가
// console.log(account.balance); // undefined
클로저 실전 예제
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 1. 함수 팩토리
function makeAdder(x) {
return function(y) {
return x + y;
};
}
const add5 = makeAdder(5);
const add10 = makeAdder(10);
console.log(add5(3)); // 8
console.log(add10(3)); // 13
// 2. 이벤트 핸들러
function setupButtons() {
const buttons = ["버튼1", "버튼2", "버튼3"];
buttons.forEach((text, i) => {
// 클로저로 i 값 기억
document.getElementById(`btn${i}`).addEventListener('click', () => {
console.log(`${text} 클릭됨 (인덱스: ${i})`);
});
});
}
// 3. 메모이제이션
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (key in cache) {
console.log("캐시에서 반환");
return cache[key];
}
console.log("계산 중...");
const result = fn(...args);
cache[key] = result;
return result;
};
}
const slowFib = n => {
if (n <= 1) return n;
return slowFib(n - 1) + slowFib(n - 2);
};
const fastFib = memoize(slowFib);
console.log(fastFib(10)); // 계산 중....55
console.log(fastFib(10)); // 캐시에서 반환 55
5. this 바인딩
일반 함수의 this
아래 코드는 javascript를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const person = {
name: "홍길동",
greet: function() {
console.log(`안녕하세요, ${this.name}입니다.`);
}
};
person.greet(); // 안녕하세요, 홍길동입니다.
// this는 호출 방법에 따라 달라짐
const greetFunc = person.greet;
// greetFunc(); // TypeError: Cannot read property 'name' of undefined
화살표 함수의 this
다음은 javascript를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const person = {
name: "홍길동",
hobbies: ["독서", "운동", "코딩"],
// 일반 함수
printHobbies1: function() {
this.hobbies.forEach(function(hobby) {
// console.log(`${this.name}의 취미: ${hobby}`); // this.name is undefined
});
},
// 화살표 함수 (this가 상위 스코프 유지)
printHobbies2: function() {
this.hobbies.forEach(hobby => {
console.log(`${this.name}의 취미: ${hobby}`); // OK
});
}
};
person.printHobbies2();
// 홍길동의 취미: 독서
// 홍길동의 취미: 운동
// 홍길동의 취미: 코딩
bind, call, apply
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const person = {
name: "홍길동"
};
function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
// call: 즉시 호출
greet.call(person, "안녕하세요", "!");
// 안녕하세요, 홍길동!
// apply: 배열로 인자 전달
greet.apply(person, ["Hello", "."]);
// Hello, 홍길동.
// bind: 새 함수 반환 (this 고정)
const boundGreet = greet.bind(person);
boundGreet("Hi", "~");
// Hi, 홍길동~
6. 콜백 함수 (Callback)
콜백이란?
콜백(Callback)은 다른 함수에 인자로 전달되는 함수입니다. 다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 기본 예제
function processArray(arr, callback) {
const result = [];
for (let item of arr) {
result.push(callback(item));
}
return result;
}
const numbers = [1, 2, 3, 4, 5];
// 제곱
const squared = processArray(numbers, x => x * x);
console.log(squared); // [1, 4, 9, 16, 25]
// 2배
const doubled = processArray(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
비동기 콜백
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// setTimeout: 일정 시간 후 실행
console.log("시작");
setTimeout(() => {
console.log("2초 후 실행");
}, 2000);
console.log("끝");
// 출력 순서:
// 시작
// 끝
// 2초 후 실행
// 콜백 지옥 (Callback Hell)
setTimeout(() => {
console.log("1초");
setTimeout(() => {
console.log("2초");
setTimeout(() => {
console.log("3초");
}, 1000);
}, 1000);
}, 1000);
// Promise로 개선 (다음 글에서)
7. 즉시 실행 함수 (IIFE)
IIFE란?
IIFE (Immediately Invoked Function Expression)는 정의와 동시에 실행되는 함수입니다. 다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 기본 형태
(function() {
console.log("즉시 실행!");
})();
// 화살표 함수
(() => {
console.log("화살표 IIFE");
})();
// 매개변수 전달
(function(name) {
console.log(`Hello, ${name}!`);
})("홍길동");
// 반환값 받기
const result = (function() {
return 10 + 20;
})();
console.log(result); // 30
IIFE 활용: 모듈 패턴
다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const counterModule = (function() {
let count = 0; // private 변수
return {
increment() {
count++;
return count;
},
decrement() {
count--;
return count;
},
getCount() {
return count;
}
};
})();
console.log(counterModule.increment()); // 1
console.log(counterModule.increment()); // 2
console.log(counterModule.getCount()); // 2
// console.log(counterModule.count); // undefined (접근 불가)
8. 재귀 함수 (Recursion)
재귀란?
재귀(Recursion)는 함수가 자기 자신을 호출하는 것입니다. 다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 팩토리얼
function factorial(n) {
if (n <= 1) return 1; // 기저 조건
return n * factorial(n - 1); // 재귀 호출
}
console.log(factorial(5)); // 120
// 피보나치
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(7)); // 13
// 배열 합계
function sumArray(arr) {
if (arr.length === 0) return 0;
return arr[0] + sumArray(arr.slice(1));
}
console.log(sumArray([1, 2, 3, 4, 5])); // 15
재귀 실전 예제
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 1. 중첩 객체 탐색
function findValue(obj, key) {
if (key in obj) {
return obj[key];
}
for (let k in obj) {
if (typeof obj[k] === 'object' && obj[k] !== null) {
const result = findValue(obj[k], key);
if (result !== undefined) {
return result;
}
}
}
return undefined;
}
const data = {
user: {
profile: {
name: "홍길동",
age: 25
}
}
};
console.log(findValue(data, "name")); // 홍길동
// 2. 디렉토리 트리 출력
function printTree(node, depth = 0) {
const indent = " ".repeat(depth);
console.log(`${indent}- ${node.name}`);
if (node.children) {
node.children.forEach(child => {
printTree(child, depth + 1);
});
}
}
const tree = {
name: "root",
children: [
{ name: "folder1", children: [
{ name: "file1.txt" },
{ name: "file2.txt" }
]},
{ name: "folder2", children: [
{ name: "file3.txt" }
]}
]
};
printTree(tree);
// - root
// - folder1
// - file1.txt
// - file2.txt
// - folder2
// - file3.txt
9. 실전 예제
예제 1: 배열 유틸리티 함수
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 배열 청크 (n개씩 나누기)
function chunk(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
console.log(chunk([1, 2, 3, 4, 5, 6, 7], 3));
// [[1, 2, 3], [4, 5, 6], [7]]
// 배열 평탄화
function flatten(arr) {
return arr.reduce((acc, item) => {
return acc.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
console.log(flatten([1, [2, 3], [4, [5, 6]]]));
// [1, 2, 3, 4, 5, 6]
// 중복 제거
function unique(arr) {
return [...new Set(arr)];
}
console.log(unique([1, 2, 2, 3, 3, 3, 4]));
// [1, 2, 3, 4]
예제 2: 함수 조합 (Composition)
다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 함수 조합
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const add1 = x => x + 1;
const double = x => x * 2;
const square = x => x * x;
const combined = compose(square, double, add1);
console.log(combined(3)); // ((3 + 1) * 2)^2 = 64
// 파이프 (왼쪽에서 오른쪽)
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const piped = pipe(add1, double, square);
console.log(piped(3)); // ((3 + 1) * 2)^2 = 64
예제 3: 디바운스와 쓰로틀
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 디바운스: 마지막 호출 후 일정 시간 대기
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func(...args), delay);
};
}
// 검색 입력 예제
const search = debounce((query) => {
console.log(`검색: ${query}`);
}, 500);
// search("a"); // 취소됨
// search("ab"); // 취소됨
// search("abc"); // 500ms 후 실행
// 쓰로틀: 일정 시간마다 한 번만 실행
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func(...args);
}
};
}
// 스크롤 이벤트 예제
const handleScroll = throttle(() => {
console.log("스크롤 중...");
}, 1000);
// window.addEventListener('scroll', handleScroll);
10. 자주 하는 실수와 해결법
실수 1: 화살표 함수의 this
다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 잘못된 방법
const person = {
name: "홍길동",
greet: () => {
console.log(`안녕하세요, ${this.name}입니다.`);
}
};
person.greet(); // 안녕하세요, undefined입니다.
// ✅ 올바른 방법
const person = {
name: "홍길동",
greet: function() {
console.log(`안녕하세요, ${this.name}입니다.`);
}
};
person.greet(); // 안녕하세요, 홍길동입니다.
실수 2: 반복문에서 클로저
다음은 javascript를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 잘못된 방법
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
// 3 3 3
// ✅ 올바른 방법 1: let 사용
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
// 0 1 2
// ✅ 올바른 방법 2: IIFE
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 100);
})(i);
}
// 0 1 2
실수 3: 객체 메서드에서 화살표 함수
다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 잘못된 방법
const counter = {
count: 0,
increment: () => {
this.count++; // this는 전역 객체
}
};
counter.increment();
console.log(counter.count); // 0 (변경 안 됨)
// ✅ 올바른 방법
const counter = {
count: 0,
increment: function() {
this.count++;
}
};
counter.increment();
console.log(counter.count); // 1
11. 연습 문제
문제 1: 커링 (Currying)
여러 인자를 받는 함수를 단일 인자를 받는 함수들의 체인으로 변환하세요. 다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
}
return (...nextArgs) => curried(...args, ...nextArgs);
};
}
// 테스트
function add(a, b, c) {
return a + b + c;
}
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6
console.log(curriedAdd(1, 2, 3)); // 6
문제 2: 함수 파이프라인
여러 함수를 순차적으로 실행하는 파이프라인을 구현하세요. 아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function pipe(...fns) {
return function(x) {
return fns.reduce((acc, fn) => fn(acc), x);
};
}
// 테스트
const add1 = x => x + 1;
const double = x => x * 2;
const square = x => x * x;
const pipeline = pipe(add1, double, square);
console.log(pipeline(3)); // ((3 + 1) * 2)^2 = 64
문제 3: 재귀로 배열 평탄화
아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
function flattenDeep(arr) {
return arr.reduce((acc, item) => {
return acc.concat(
Array.isArray(item) ? flattenDeep(item) : item
);
}, []);
}
// 테스트
const nested = [1, [2, [3, [4, 5]]], 6];
console.log(flattenDeep(nested)); // [1, 2, 3, 4, 5, 6]
정리
핵심 요약
- 함수 정의:
- 선언문: 호이스팅됨
- 표현식: 호이스팅 안 됨
- 화살표 함수: 간결, this 렉시컬
- 매개변수:
- 기본 매개변수:
function(x = 10) - 나머지 매개변수:
function(...args) - 구조 분해:
function({ name, age })
- 기본 매개변수:
- 고차 함수:
- 함수를 인자로 받기
- 함수를 반환하기
map,filter,reduce
- 클로저:
- 외부 변수 기억
- 프라이빗 변수 구현
- 메모이제이션
- this 바인딩:
- 일반 함수: 동적
- 화살표 함수: 렉시컬
bind,call,apply
베스트 프랙티스
- ✅ 화살표 함수 우선 (this 불필요시)
- ✅ 순수 함수 작성 (부작용 최소화)
- ✅ 함수는 한 가지 일만
- ✅ 의미 있는 함수명
- ✅ 매개변수 3개 이하 권장
다음 단계
- JavaScript 배열과 객체
- JavaScript 비동기 프로그래밍
- JavaScript 클래스