react 게시판을 만들면서 화살표 함수를 많이 썼는데, 화살표 함수에 대해서 정리가 필요하다는 생각이 들었다
0. 화살표 함수란?
화살표 함수란 무엇일까?
= () => { }
위 문법은 화살표 함수(arrow function)을 정의하는 JavaScript 문법이다
ES6(ECMAScript 2015)에서 도입되었으며, 기존 함수 표현식보다 간결하게 작성할 수 있다
1. 기본 문법
const 함수명 = (매개변수) => {
//함수 내용
};
- 간결한 함수 정의 : 기존 function 키워드를 사용한 정의보다 간단함
- this의 바인딩 : 화살표 함수는 자신만의 this를 가지지 않고 정의된 렉시컬 컨텍스트(lexical context)**의 this를 사용한다
- 반환값 생략 가능 : 중괄호를 생략하면 바로 반환값을 작성할 수 있다
const add = (a, b) => a + b; //return 키워드 없이도 결과를 반환
2. 설명
2-1. 간단한 예시를 통한 설명
const UpdateEffectExample = () => {
// 컴포넌트 내용
const [count, setCount] = useState(0);
const [text, setText] = useState('');
}
React에서 컴포넌트를 함수형으로 정의할 때는 일반적으로 함수 선언이나 화살표 함수를 사용한다
화살표 함수를 자주 사용하는 이유는
1) this 문제 회피
클래스형 컴포넌트와 달리 함수형 컴포넌트는 this를 사용할 일이 거의 없다
화살표 함수는 this 바인딩 문제를 자연스럽게 해결해준다
2) 간결한 문법
컴포넌트가 단순히 상태를 처리하고 JSX를 반환할 때 화살표 함수가 더 깔끔하다
2-2. 기존 함수 표현식과의 차이
기존 함수 표현식
function UpdateEffectExample() {
// 컴포넌트 내용
}
화살표 함수 표현식
const UpdateEffectExample = () => {
// 컴포넌트 내용
}
차이점
- 화살표 함수는 function 키워드를 사용하지 않아 간결하며 선언 방식이 익명 함수처럼 동작한다
- this와 관련된 상황에서 동작이 다르다. 화살표 함수는 상위 스코프의 this를 사용한다
2-3. 다양한 예제
// 1. 매개변수가 없는 경우
const sayHello = () => {
return 'Hello';
};
console.log(sayHello()); //출력 : Hello!
// 2. 매개변수가 하나인 경우 (괄호 생략 가능)
const square = x => {
return x*x;
};
console.log)(square(4)); //출력 : 16
// 3. 여러 매개변수
const add = (a, b) => {
return a+b;
};
console.log(add(3, 5)); //출력 : 8
// 4. 중괄호와 'return' 생략 가능(한 줄로 작성 시)
const multiply = (a, b) => a * b;
console.log(multiply(2, 3)); //출력 : 6
3. 주요 특징
3-1. this의 바인딩
화살표 함수는 자체적인 this를 가지지 않고, 상위 스코프의 this를 사용한다
// 일반 함수에서는 'this'가 동적으로 바인딩됨
function RegularFunction(){
this.value = 10;
setTimeout(function () {
console.log(this.value); //undefined (setTimeout 내부의 this는 글로벌 객체를 가리킴)
}, 1000);
}
// 화살표 함수는 상위 스코프의 'this'를 사용
function ArrowFunction() {
this.value = 10;
setTimeout(() => {
console.log(this.value); //10
}, 1000);
}
new RegularFunction();
new ArrowFunction();
3-2. arguments 객체 없음
화살표 함수는 자체적인 arguments 객체를 가지지 않는다
필요한 경우 ...rest 문법을 사용해야한다
function regularFunction(){
console.log(arguments); // [1, 2, 3]
}
const arrowFunction = (...args) => {
console.log(args); // [1, 2, 3]
};
regularFunction(1, 2, 3);
arrowFunction(1, 2, 3);
3-3. 생성자로 사용 불가
화살표 함수는 생성자 함수로 사용할 수 없다
new 키워드를 사용하면 에러가 발생한다
const Person = (name) => {
this.name = name;
};
const p = new Person('Alice'); //TypeError : Person is not a constructor
3-4. return 생략 가능
함수 본문이 한 줄이고 결과를 바로 반환할 경우,
중괄호와 return을 생략할 수 있다
const double = x => x * 2; //return 키워드 생략
console.log(double(4)); //8
4. 장점
4-1. 간결한 문법
코드가 짧고 가독성이 높다
4-2. this 사용
클래스나 객체 내부에서 콜백 함수로 사용시 this 문제가 해결한다
4-3. 표현식 중심
간단한 계산이나 변환 작업에 적합하다
5. React 함수형 컴포넌트에서 사용 주의점
화살표 함수를 사용하는 것은 React 함수형 컴포넌트를 정의할 때 좋지만
다음의 상황에서는 사용에 유의해야한다
- 이벤트 핸들러를 사용할 때, 화살표 함수를 렌더링 시점마다 생성하지 않도록 주의해야 함
- 불필요한 렌더링을 막기 위해 React.memo를 사용해 최적화를 고려해야한다
5-1. 객체 리터럴 반환 시 주의
객체로 바로 반환하려면 괄호()를 사용해 감싸야 한다
그렇지 않으면 중괄호를 함수 본문으로 오해할 수 있다
const getObject = () => ({ key : 'value' }); //괄호로 감싸야 객체를 반환
console.log(getObject()); //{ key: 'value' }
5-2. this 바인딩 주의
화살표 함수는 this를 상위 스코프에서 가져오기 때문에 this가 필요한 상황에서는 일반함수가 더 적합할 수 있다
const obj = {
value: 42,
method: () => console.log(this.value), //화살표 함수는 상위 스코프의 'this'를 사용
};
obj.method(); //undefined (상위 스코프는 글로벌 컨텍스트)
5-3. prototype 속성이 없음
화살표 함수는 prototype 속성을 가지지 않으므로 프로토타입 메소드를 정의할 수 없다
const MyClass = () => {};
console.log(MyClass.prototype); //undefined
5-4. 상황에 맞는 사용
이벤트 핸들러에서 this를 의도적으로 다뤄야 할 경우 일반함수가 더 적합할 수 있다
객체 메소드 정의에는 일반 함수가 더 권장된다
6. 렉시컬 스코프 쉽게 이해하기
"함수를 어디에서 선언했는지"에 따라 변수가 결정되는 규칙을 말한다
즉 함수가 실행되는 위치와는 상관없이, 함수가 작성된 코드 위치를 기준으로 스코프(변수 접근 범위)가 결정된다는 뜻
6-1. 쉽게 이해하기
① 코드의 작성 위치가 중요
함수가 어디에서 선언되었는지가 중요하다
② 안에서 밖으로 찾는 방식
함수 내부에서 변수를 찾을 때 먼저 함수 내부(자기 자신의 스코프)에서 찾는다
→ 없으면 한 단계 위(부모 스코프)로 올라가 찾는다
→ 그래도 없다면 최종적으로 전역 스코프까지 올라간다
6-2. 예제
① 함수가 선언된 위치를 기준으로 변수 찾기
const outerVar = "바깥 변수";
function outerFunction() {
const innerVar = "안쪽 변수";
function innerFunction() {
console.log(outerVar); // "바깥 변수" 출력
console.log(innerVar); // "안쪽 변수" 출력
}
innerFunction();
}
outerFunction();
▷innerFunction은 outerFunction 안에서 선언되었기 때문에
outerFunction의 변수에 접근할 수 있다
▷innerFunction이 실행될 때는 자기 스코프에서 변수를 찾고, 없으면 바깥 스코프(부모 함수)를 순차적으로 탐색한다
② 선언 위치가 중요
const globalVar = "전역 변수";
function exampleFunction() {
console.log(globalVar);
}
function anotherFunction() {
const globalVar = "다른 전역 변수";
exampleFunction();
}
exampleFunction(); //"전역 변수" 출력
anotherFunction(); //"전역 변수" 출력
▷ exampleFunction은 전역 스코프에서 선언되었기 때문에
항상 전역 스코프에서 globalVar를 찾는다
▷anotherFunction 안에서 실행되더라도 exampleFunction의 선언 위치는 변하지 않으므로,
전역 변수 globalVar를 참조한다
6-3. 렉시컬 스코프와 화살표 함수
화살표 함수에서 렉시컬 스코프가 중요한 이유는 화살표 함수의 this도 선언된 위치를 기준으로 결정되기 때문이다
function Person(name) {
this.name = name;
//화살표 함수
this.sayName = () => {
console.log(this.name);
}
}
const person = new Person("Alice");
person.sayName(); //"Alice" 출력
▷sayName 화살표 함수는 Person 함수 내부에서 선언되었다
▷this는 Person 함수의 this를 그대로 사용한다
▷렉시컬 스코핑 때문에 this.name은 Alice로 유지된다
☞ 렉시컬 스코프는 "코드 작성 위치"를 기준으로 변수와 this를 찾는 규칙이다
7. 화살표 함수와 일반함수의 차이점 정리
특성 | 일반함수 | 화살표 함수 |
this | 호출 방식에 따라 바뀜 | 선언된 위치의 상위 스코프를 고정된 this로 사용 |
arguments | 자체 arguments 객체를 제공 | 자체 arguments 없음. 상위 스코프의 arguments 사용 |
prototype | 있음(생성자 함수로 사용 가능) | 없음 (생성자 함수로 사용 불가) |
8. 화살표 함수는 언제 사용해야 할까?
8-1. 콜백 함수
▷ this가 상위 스코프의 값을 유지해야 할 때 유용함
const person = {
name: 'Alice',
greet: function () {
setTimeout(() => {
console.log('Hello, ${this.name}'); //'this'는 person을 참조
}, 1000);
},
};
person.greet(); // Hello, Alice
8-2. 간단한 연산 함수
▷map, filter, reduce 같은 배열 메소드와 잘 어울림
const numbers = [1, 2, 3];
const squares = numbers.map(n => n * n);
console.log(squares); // [1, 4, 9]
8-3. 일반 함수가 필요한 경우
생성자 함수, 객체 메소드 또는 arguments 객체를 직접 사용해야 할 때는 일반 함수를 사용한다
'개발 기록 > front - react' 카테고리의 다른 글
[React] React 컴포넌트 생명주기, 생명주기 메소드 (0) | 2024.11.26 |
---|---|
[react] React 컴포넌트와 Props, State (1) | 2024.11.25 |
React의 UseEffect는 왜 두 번씩 실행되어 빡치게 만드는가 (1) | 2024.11.16 |
[REACT] Failed to compile. Module not found : Can't resolve 'react-router-dom' (1) | 2024.11.04 |
[REACT] npm 패키지 설치 중 warn 이슈 - fsevents, requires a peer of typescript (0) | 2024.10.31 |