티스토리 뷰
목차
1. 화살표 함수란?
2. 기본문법
3. this
4. 화살표 함수의 this 바인딩
5. 화살표 함수를 쓰면 안되는 경우
1. 화살표 함수란?
화살표 함수는 ES6 에서 새로 등장한 함수 선언 방법이다. function 키워드를 사용해서 함수를 만든 것 보다 간단히 함수를 표현할 수 있다.
// 일반 함수(함수 표현식)
const sum = function(x, y) {
return x + y;
}
sum(3, 4); //7
// 함수 선언식: function 키워드로 단독으로 함수를 선언한 것
// function sum(x,y) {
// return x + y;
// }
또한 화살표 함수는 익명 함수이다.
// 화살표 함수
const sum = (x, y) => x + y;
sum(3, 4); //7
2. 기본 문법
화살표 함수 표현(arrow function expression)은 function 표현에 비해 구문이 짧고 자신의 this, arguments, super 또는 new.target을 바인딩 하지 않습니다. 화살표 함수는 항상 익명입니다. 이 함수 표현은 메소드 함수가 아닌 곳에 가장 적합합니다. 그래서 생성자로서 사용할 수 없습니다.
-MDN
화살표 함수의 기본구문은 다음과 같다.
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 다음과 동일함: => { return expression; }
// 매개변수가 하나뿐인 경우 괄호는 선택사항:
(singleParam) => { statements }
singleParam => { statements }
// 매개변수가 없는 함수는 괄호가 필요:
() => { statements }
const foo = (a, b) => {
return (a + b) * 10;
};
1. 매개 변수가 하나인 경우, 소괄호를 생략할 수 있다.
const foo = a => {
return a * 10;
};
또한 위의 코드처럼 중괄호 안에 return을 반환하고 있다면 좀 더 간단하게 줄일 수있다.
const foo = a => a * 10;
//"{}"를 사용하면 값을 반환할 때 return을 사용해야합니다.
//"{}"를 사용하지 않으면 undefied를 반환합니다.
//"{}"을 사용할 때는 여러줄을 썼을 때 사용합니다.
2. 매개 변수가 하나도 없는 경우, 다음과 같이 적을 수 있다.
const printPie = () => 3.14
3. 함수가 하나의 실행문만 가지고 있다면 중괄호를 생략할 수 있다. 간단하게 한 줄로 표현할 때는 "{}" 없이 값이 반환된다.
const foo = (a, b) => a + b;
foo(1, 2); //3 (foo 화살표함수의 반환값)
3. this
function 키워드로 생성한 일반 함수와 화살표 함수의 가장 큰 차이점은 this다.
대표적으로 this에 바인딩되는 값들은 다음과 같다.
- 전역 공간의 this : 전역 객체
- 메소드 호출 시 메소드 내부의 this : 해당 메소드를 호출한 객체
- 함수 호출 시 함수 내부의 this : 지정되지 않음(?)
...
1,2 번은 이해가 되지만 3번이 이상하다.
함수를 호출했을 때 그 함수 내부의 this는 지정되지 않는다. 그리고 this가 지정되지 않은 경우, this는 자동으로 전역 객체를 바라보기 때문에 함수를 호출하면 함수 내부에서의 this는 전역 객체가 된다고 정리할 수 있다.
아쉽게도 이것은 자바스크립트 개발자 중 한 명인 더글라스 크락포드조차 이 점은 설계상의 오류라고 지적했다.
예제
그냥 함수를 호출한다면 다음과 같은 상황이 연출된다.
const cat = {
name: 'meow',
foo1: function() {
const foo2 = function() {
console.log(this.name);
}
foo2();
}
};
cat.foo1(); // undefined
- cat.foo1() 메소드 호출 시 내부 함수 foo2가 실행됨
- 함수가 호출됐으므로 foo2 내부의 this는 지정되지 않아서 곧 전역 객체를 가리킴
- 전역 객체에 name이란 속성은 존재하지 않으므로 undefined가 뜸
당연히 this.name은 cat 객체의 내부에 지정한 'meow'일 줄 알았는데 undefined가 도출된다. 하지만 이것은 화살표 함수로 해결할 수 있습니다.
const cat = {
name: 'meow',
foo1: function() {
const foo2 = () => {
console.log(this.name);
}
foo2();
}
};
cat.foo1(); // meow
위 코드와 달라진 점은 cat 객체의 내부함수 foo2가 화살표 함수로 선언됐다는 점 이다. 그런데 이번엔 의도한대로 meow가 잘 찍혔다. 어떻게 가능한걸까?
4. 화살표 함수의 this 바인딩
이것이 가능한 이유는 화살표 함수에는 this가 아예 없기 때문이다.
즉, function으로 선언한 함수를 실행할 땐 this가 존재하긴 하지만 값을 지정하지 않는데, 화살표 함수로 선언한 함수에는 this가 없다.
- JavaScript에서는 어떤 식별자(변수)를 찾을 때 현재 환경에서 그 변수가 없으면 바로 상위 환경을 검색한다. 그렇게 점점 상위 환경으로 타고 타고 올라가다가 변수를 찾거나 가장 상위 환경에 도달하면 그만두게 되는 것이다. 화살표 함수에서의 this 바인딩 방식도 이와 유사하다. 화살표 함수에는 this라는 변수 자체가 존재하지 않기 때문에 그 상위 환경에서의 this를 참조하게 된다.
더 정확히는, function으로 선언한 함수가 메소드로 호출되냐 함수 자체로 호출되냐에 따라 동적으로 this가 바인딩되는 반면, 화살표 함수는 선언될 시점에서의 상위 스코프가 this로 바인딩된다.
5. 화살표 함수를 쓰면 안되는 경우
이렇게 JavaScript의 함수 this 바인딩 문제를 깔끔하게 해결해 준 화살표 함수도 사용해선 안되는 때가 있다. 상위 환경의 this를 참조한다는 점이 문제가 될 수도 있기 때문이다.
1. 메소드
const cat = {
name: 'meow';
callName: () => console.log(this.name);
}
cat.callName(); // undefined
이 같은 경우 callName 메소드의 this는 자신을 호출한 객체 cat이 아니라 함수 선언 시점의 상위 스코프인 전역객체를 가리키게 됩니다.
2. 생성자 함수
const Foo = () => {};
const foo = new Foo() // TypeError: Foo is not a constructor
화살표 함수를 생성자함수로 사용하면 에러가 납니다. 생성자 함수로는 사용할 수 없게 만들어졌기 때문입니다.
3. addEventListener()의 콜백함수
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this); // Window
this.innerHTML = 'clicked';
});
button.addEventListener('click', function() {
console.log(this); // button 엘리먼트
this.innerHTML = 'clicked';
});
원래 addEventListener의 콜백함수에서는 this에 해당 이벤트 리스너가 호출된 엘리먼트가 바인딩되도록 정의되어 있다.
이처럼 이미 this의 값이 정해져있는 콜백함수의 경우, 화살표 함수를 사용하면 기존 바인딩 값이 사라지고 상위 스코프(이 경우엔 전역 객체)가 바인딩되기 때문에 의도했던대로 동작하지 않을 수 있다.
물론 상위 스코프의 속성들을 쓰려고 의도한 경우라면 사용할 수 있다.
'Language > JavaScript' 카테고리의 다른 글
[Javascript] 객체 object (0) | 2022.06.29 |
---|---|
[Javascript] 음식 팁과 총액을 계산하는 문제 (0) | 2022.06.28 |
[Javascript] append() 와 appendChild() 차이 (+ prepend) (0) | 2022.06.24 |
[JavaScript] for...in문, for...of문, forEach문 (0) | 2022.06.24 |
[Javascript] querySelectorAll (0) | 2022.06.23 |
- Total
- Today
- Yesterday
- 리액트
- map
- hydrationboundary
- 유사배열객체
- CSS
- 프론트엔드
- rest parameter
- 코드잇스프린트
- js
- 동기
- 비제어 컴포넌트
- 배열
- currentTarget
- Next.js
- Git
- 객체
- 스프린트프론트엔드6기
- innerhtml
- GitHub
- 제어 컴포넌트
- arguments
- 취업까지달린다
- 코드잇 스프린트
- Target
- html
- 비동기
- javascript
- react
- 중급 프로젝트
- tanstackquery
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |