JavaScript에서 함수를 정의하는 방식은 다양하지만,
대표적으로 function 키워드로 만든 일반 함수와 => 로 정의하는 화살표 함수가 있습니다.
이 둘을 구분하지 않고 섞어 쓰면 this나 arguments 관련 버그가 생길 수 있습니다.
이번 글에서는 두 함수의 핵심 차이점에 대해 알아보겠습니다.
문법 차이와 간결함
기본 단순 함수부터 매개변수 하나, return 생략, 객체 리턴까지 다양한 형태를 직관적으로 비교해보겠습니다.
// 일반 함수
function greet(name) {
return 'Hello, ' + name;
}
// 함수 표현식
const greet2 = function(name) {
return 'Hi, ' + name;
}
// 화살표 함수
const greetArrow = (name) => {
return `Hey, ${name}`;
}
// 매개변수가 하나일 때 ( ) 생략 가능
const greetArrowShort = name => `Hey, ${name}`;
// {}와 return 생략 가능 (한 줄 표현 시)
const sum = (a, b) => a + b;
// 객체 반환 시 괄호 () 필수
const makeUser = (id, name) => ({ id, name });
this 바인딩
가장 큰 차이 중 하나는 바로 this의 동작 방식입니다.
this가 무엇을 가리키느냐에 따라 함수의 동작 방식이 완전히 달라지죠.
const user = {
name: 'Alice',
sayNameRegular: function() {
console.log('regular:', this.name);
},
sayNameArrow: () => {
console.log('arrow:', this.name);
}
};
user.sayNameRegular(); // Alice
user.sayNameArrow(); // undefined
- 일반 함수: this가 해당 객체(user)를 가리킵니다.
- 화살표 함수: 정의된 스코프(여기선 전역)를 따라 this가 고정됩니다.
📌예시 : 클래스 안에서의 화살표 함수 vs 일반 함수
class Counter {
count = 0;
regularMethod() {
setTimeout(function() {
this.count++;
console.log('regularMethod count:', this.count);
}, 100);
}
arrowMethod() {
setTimeout(() => {
this.count++;
console.log('arrowMethod count:', this.count);
}, 100);
}
}
const c = new Counter();
c.regularMethod(); // NaN, this는 전역
c.arrowMethod(); // 1, this는 인스턴스
- setTimeout 내부의 화살표 함수는 Counter 인스턴스의 this를 그대로 가리켜 올바른 값 갱신이 가능합니다.
- 일반 함수는 자신의 this가 독립적이라 잘못된 참조로 이어질 수 있습니다.
arguments 객체
일반 함수는 내부에 arguments 객체를 사용할 수 있죠.
반면 화살표 함수에는 arguments가 없기 때문에 Rest(...args)를 사용해야 합니다.
function sumAll() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
const sumAllArrow = (...args) => args.reduce((a, b) => a + b, 0);
console.log(sumAll(1, 2, 3)); // 6
console.log(sumAllArrow(1, 2, 3)); // 6
⚠️ 화살표 함수 내부에서 arguments를 쓰면 ReferenceError가 발생하므로,
✅ 가변 매개변수가 필요할 땐 Rest를 사용하면 됩니다.
생성자 함수 사용 여부
function Person(name) {
this.name = name;
}
const p1 = new Person('Bob'); // OK
const PersonArrow = (name) => {
this.name = name;
};
const p2 = new PersonArrow('Charlie'); // TypeError
- 일반 함수는 new 키워드를 붙여 생성자처럼 사용할 수 있습니다.
- 화살표 함수는 생성자 함수로 사용할 수 없음 → new 사용 시 에러 발생!
콜백 함수 활용
콜백으로 함수를 넘길 때도 화살표 함수가 더 편리한 면이 있습니다.
const nums = [1, 2, 3];
const doubled1 = nums.map(function(n) {
return n * 2;
});
const doubled2 = nums.map(n => n * 2);
console.log(doubled1, doubled2);
✅ 짧고 읽기 쉬워서 함수 내에 로직이 복잡하지 않다면 화살표 함수가 매우 유리합니다.
클래스 내부 활용 예시
class TodoApp {
constructor() {
this.todos = [];
document.getElementById('btn').addEventListener('click', () => {
this.todos.push('할일');
console.log(this.todos);
});
}
}
정리
상황 | 일반 함수 | 화살표 함수 |
객체 메서드 정의 시 | ✅ 사용 권장 | ❌ 피해야 함 (this 문제) |
콜백 함수 (map, filter 등) | ⚠️ 가능하지만 장황 | ✅ 가장 적합 |
이벤트 핸들러 안쪽 함수 | ✅ 설명 필요 | ✅ this 유지에 유리 |
생성자 함수 (new로 사용할 때) | ✅ 사용 가능 | ❌ 사용 불가 |
arguments 객체 사용 필요할 때 | ✅ 지원됨 | ❌ ...args 로 대체해야 함 |
가독성 중시, 간단한 함수 | ⚠️ 다소 장황 | ✅ 명확하고 간결한 표현 |
- 짧고 간단한 함수, 콜백 ➡️ 화살표 함수
- 메서드, 생성자, arguments 필요 ➡️ 일반 함수
화살표 함수는 코드를 간결하게 만들고, this 바인딩 문제를 줄이는 데 유용합니다.
하지만 모든 상황에서 무조건 사용하는 것은 오히려 문제를 일으킬 수 있습니다.
상황에 맞게 두 함수의 특성을 이해하고 선택하는 것이 중요합니다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 배열의 map() 과 filter() (0) | 2024.07.23 |
---|---|
[JavaScript] push()와 concat()의 차이점 (0) | 2024.07.22 |
[JavaScript] 변수 생성 키워드 var, let, const (0) | 2024.06.29 |