[TIL] 자바스크립트 함수 완벽 이해하기 - function vs 화살표 함수의 차이
개발자로서 성장하면서 자바스크립트의 함수에 대해 깊이 있게 이해하는 것은 정말 중요합니다. 특히 ES6에서 도입된 화살표 함수는 기존 function 키워드로 선언하는 함수와 미묘하지만 중요한 차이가 있는데요. 이번 글에서는 제가 실제 프로젝트를 진행하면서 겪었던 경험을 바탕으로 두 함수의 차이점을 자세히 살펴보려고 합니다.
들어가며 - 왜 이런 차이를 알아야 할까?
처음 자바스크립트를 배울 때는 function 키워드로 함수를 만들다가, 어느 순간부터 화살표 함수를 사용하게 됩니다. "뭐... 그냥 더 짧게 쓸 수 있어서 좋네!" 하고 넘어갈 수도 있지만, 실제로 프로젝트를 하다 보면 이 둘의 차이 때문에 의도치 않은 버그를 마주치게 되죠.
1. this의 동작방식 차이
가장 먼저 살펴볼 것은 this
입니다. 프론트엔드 개발을 하다 보면 이벤트 핸들러나 타이머 함수에서 this
때문에 골치 아픈 경우가 정말 많았는데요.
const myButton = {
content: '클릭해주세요',
click: function() {
console.log(this.content); // '클릭해주세요' 출력
setTimeout(function() {
console.log(this.content); // undefined 출력 😱
}, 1000);
}
}
위 코드에서 setTimeout 안의 일반 함수는 자신만의 this
를 가지기 때문에 우리가 원하는 대로 동작하지 않습니다. 이전에는 이런 문제를 해결하기 위해 bind(this)
를 사용하거나 that = this
와 같은 꼼수를 써야 했죠.
하지만 화살표 함수를 사용하면 이런 고민을 하지 않아도 됩니다.
const myButton = {
content: '클릭해주세요',
click: function() {
console.log(this.content); // '클릭해주세요' 출력
setTimeout(() => {
console.log(this.content); // '클릭해주세요' 출력 ✨
}, 1000);
}
}
화살표 함수는 자신만의 this
를 생성하지 않고 외부 스코프의 this
를 그대로 사용하기 때문에, 우리가 예상한 대로 동작하게 됩니다.
2. 생성자 함수로 사용할 수 없다?
화살표 함수의 또 다른 특징은 생성자 함수로 사용할 수 없다는 점입니다. 처음에는 이게 왜 중요한지 몰랐는데, 클래스 기반 프로그래밍을 할 때 이 차이가 매우 중요하다는 걸 알게 되었습니다.
// 일반 함수로는 가능
function Person(name) {
this.name = name;
}
const person1 = new Person('김코딩'); // 잘 동작합니다!
// 화살표 함수로는 불가능
const Person2 = (name) => {
this.name = name;
}
const person2 = new Person2('박해커'); // TypeError! 🚫
이런 제약이 있는 이유는 화살표 함수가 prototype
프로퍼티를 가지지 않기 때문입니다. 자바스크립트에서 생성자 함수가 되려면 prototype
객체가 필요한데, 화살표 함수는 이를 가지고 있지 않죠.
3. arguments 객체의 차이
이건 제가 실제로 겪었던 재미있는 경험인데요. 가변 인자를 처리하는 함수를 만들다가 발견한 차이점입니다.
function regularSum() {
// arguments 객체를 사용할 수 있습니다
return Array.from(arguments).reduce((sum, num) => sum + num, 0);
}
const arrowSum = () => {
// ReferenceError! arguments를 사용할 수 없습니다 😱
return Array.from(arguments).reduce((sum, num) => sum + num, 0);
}
화살표 함수에서는 arguments
객체를 사용할 수 없습니다. 대신 rest 파라미터를 사용해야 하죠.
const arrowSum = (...numbers) => {
return numbers.reduce((sum, num) => sum + num, 0);
};
실제 프로젝트에서는 어떻게 활용할까?
제가 리액트로 프로젝트를 진행하면서 정립한 나만의 규칙이 있는데요:
이벤트 핸들러나 콜백 함수는 화살표 함수를 사용합니다.
// 리액트 컴포넌트에서 handleClick = () => { this.setState({ clicked: true }); }
객체의 메서드는 일반 함수를 사용합니다.
const calculator = { result: 0, add(number) { this.result += number; return this; } };
유틸리티 함수는 상황에 따라 선택합니다.
// 간단한 계산 함수는 화살표 함수로 const square = x => x * x;
// this를 사용하거나 복잡한 로직이 필요한 경우 일반 함수로
function deepClone(obj) {
// 복잡한 로직...
}
```
마무리하며
처음에는 단순히 "화살표 함수가 더 짧아서 좋다"고 생각했지만, 실제 개발을 하다 보니 각각의 함수가 가진 특징을 잘 이해하고 적절한 상황에 사용하는 것이 훨씬 중요하다는 것을 깨달았습니다.
앞으로 함수를 작성할 때는 다음과 같은 질문을 해보세요:
- this 바인딩이 필요한가?
- 생성자 함수로 사용될 수 있는가?
- arguments 객체가 필요한가?
이러한 고민을 통해 더 견고한 코드를 작성할 수 있을 거예요. 여러분도 이런 차이점들을 잘 활용해서 더 나은 코드를 작성하시길 바랍니다! 😊
참고자료
- MDN Web Docs
- JavaScript Deep Dive (도서)
- 실전 리액트 프로그래밍 (도서)
'개발일지' 카테고리의 다른 글
JavaScript Set과 Map: 데이터를 효율적으로 다루는 방법 (0) | 2024.12.02 |
---|---|
자바스크립트 함수 완벽 가이드: 함수 표현식부터 모던 자바스크립트까지 (0) | 2024.11.30 |
[TIL] 자바스크립트 옵셔널 체이닝 연산자(?.) 완벽 가이드 (0) | 2024.11.28 |
Java Map 깊이 이해하기: HashMap vs TreeMap vs ConcurrentHashMap (0) | 2024.11.28 |
Java Set: HashSet, TreeSet, LinkedHashSet 완벽 가이드 (0) | 2024.11.28 |