화살표 함수를 표현할 수 있는 방식
// 매개변수가 없을 경우
() => { ... }
// 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
x => { ... }
// 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
(x, y) => { ... }
- 함수 몸체 표현
함수 몸체 내의 코드가 한 줄이고, 단순히 return 문 밖에 없다면 중괄호와 return 키워드를 생략할 수 있다.
```javascript
x => { return x * x };
// 함수 몸체가 한 줄의 구문이라면, 중괄호를 생략할 수 있으며 암묵적으로 return된다.
// 위 표현과 동일하다
x => x * x;
() => { return { a:1}; }
// 위 표현과 동일, 객체 반환시 소괄호를 사용한다.
() => ({a:1});
자바스크립트의 화살표 함수는 function
함수를 축약하여 표현하는 문법이지만, 일반적인 함수와 다른 몇 가지 고유한 특징을 가진다.
이러한 특징은 화살표 함수를 유용하게 만들기도 하지만, 함정이 되기도 하기 때문에 유의깊게 살펴보아야 한다.
화살표 함수에는 this
가 존재하지 않는다.
그래서 화살표 함수에서 this 키워드로 접근하면, 자신이 아닌 상위 환경에서 값을 가져오게 된다.
화살표 함수는 자신만의 this를 가지지 않기 때문에, 자신을 감싸는 상위 환경의 this를 그대로 따르기 때문이다.
즉, 화살표 함수에서 this는 정적으로 결정된다.
예를 들어 user
라는 객체의 sayHi
의 프로퍼티가 어떠한 형태의 함수로 이루어져 있느냐에 따라 this.name
이 가리키는 값이 달라지게 된다.
let name = "Global";
let user = {
name: 'dobby',
sayHi: function() {
console.log(this.name);
}
};
user.sayHi(); // dobby
let user = {
name: 'dobby',
sayHi: () => {
console.log(this.name);
}
};
user.sayHi(); // Global
화살표 함수는 함수가 선언된 시점의 상위 스코프에서 this를 찾는다.
자바스크립트 함수의 arguments
는 일반적으로 함수가 호출될 때 전달된 인수들을 담고 있는 유사 배열 객체이다.
function argsFunc() {
console.log(arguments);
}
argsFunc(1, 2, 3); // [1, 2, 3]
화살표 함수는 일반 함수와는 다르게, 모든 인수에 접근할 수 있게 해주는 유사 배열 객체인 arguments
를 지원하지 않는다.
따라서 실행하면 다음과 같이 에러가 발생하게 된다.
const argFunc = () => {
console.log(arguments);
}
argsFunc(1,2,3); // Error
대신에, 나머지 매개변수라는 문법을 사용하여 인수들을 배열로 받을 수 있다.
const argsFunc = (...args) => {
console.log(args);
}
argsFunc(1,2,4); // [1,2,3]
생성자 함수
란 new 연산자와 함께 호출되어 객체를 생성하는 함수를 말한다.
function User(name) {
this.name = name;
}
const user = new User('dobby');
console.log(user.name); // dobby
화살표 함수는 this
가 없기 때문에 new
와 함께 실행할 수 없다.
따라서 화살표 함수는 new와 함께 호출할 수 없다.
화살표 함수는 객체를 생성하는 용도로 사용할 수 없으며, 보통 콜백 함수나 익명 함수로서 사용되는 편이다.
화살표 함수는 일반 함수와는 달리 자신만의 this를 가지지 않는다.
그래서 화살표 함수를 자바스크립트에서 사용함에 있어 몇 가지 제약이 생긴다.
만일 this 참조를 자주 사용해야할 메소드 로직이라면, 일반 객체의 메소드로서 화살표 함수 사용은 피해야 한다.
왜냐하면, this가 없으니 메소드를 호출한 객체를 가리키지 않고 상위 컨텍스트인 전역 객체 window를 가리키게 되기 때문이다.
화살표 함수로 정의된 메소드를 prototype
객체로서 할당하는 경우도 위와 같은 동일한 문제가 발생한다.
따라서 prototype
에 메소드를 할당하는 경우, 일반 함수를 할당하도록 한다.
const person = {
name: 'dobby',
}
Object.prototype.sayHi = () =>. console.log(`Hi ${this.name}`);
// 모든 객체는 기본적으로 Object 객체에 프로토타입 체이닝 되어있다.
person.sayHi(); // Hi undefined
생성자 함수는 prototype
프로퍼티를 가지며, prototype
프로퍼티가 가리키는 Prototype Object
의 constructor
를 사용한다.
하지만, 화살표 함수는 prototype
프로퍼티를 가지고 있지 않기 때문에 위와 같은 이유로 사용하면 안된다.
const Foo = (name) => {
this.name = name;
}
console.log(Foo.hasOwnProperty('prototype')); // false
const foo = new Foo('FFF'); // TypeError
화살표 함수를 addEventListener
함수의 콜백 함수로 사용할 때도 주의해야 한다.
addEventListner
함수는 이벤트가 발생할 때마다 콜백 함수를 호출하는데, 이때 콜백 함수의 this는 이벤트가 발생한 요소를 가리키게 된다.
<button>Click me!</button>
<script>
let button = document.querySelector('button');
button.addEventListener('click', function() {
console.log(this); // <button> 요소
});
</script>
하지만 화살표 함수를 콜백 함수로 사용하면, this는 외부 렉시컬 환경의 this를 가리키게 되므로, 원하는 결과가 나오지 않을 수 있다.
<button>Click me!</button>
<script>
let button = document.querySelector('button');
button.addEventListener('click', () => {
console.log(this); // window 객체
});
</script>
따라서 addEventListenr
함수 내에서 this 키워드를 사용하는 경우엔, 화살표 함수 대신 일반적인 함수를 사용하는 것이 올바르다.
하지만, 현업에서는 forEach
와 더불어 addEventListener
함수의 콜백 함수를 코드 표현의 간략화를 위해 화살표 함수를 쓰는 사례가 많다.
따라서 이런 경우에는 this 키워드를 사용하지 말고, addEventListener
함수의 매개변수인 event
객체의 currentTarget
혹은 target
프로퍼티를 사용하여 이벤트가 발생한 요소에 접근하는 편이다.
<button>Click me!</button>
<script>
let button = document.querySelector('button');
button.addEventListener('click', (event) => {
console.log(event.target); // <button> 요소
});
</script>
보통 자바스크립트에서 this 키워드를 조작하는 대표적인 방법으로,
call
, apply
, bind
함수를 이용한 기법이 있다.
이는 화살표 함수에는 통하지 않는다.
간단하게, 화살표 함수는 this 자체가 없기 때문이다.
const obj1 = { message: 'Hello from obj1' };
const obj2 = { message: 'Hello from obj2' };
// 일반 함수
function normalFunction() {
console.log(this.message);
}
// 화살표 함수
const arrowFunction = () => {
console.log(this.message);
};
// 일반 함수에서 this 변경
normalFunction.call(obj1); // 'Hello from obj1'
normalFunction.call(obj2); // 'Hello from obj2'
// 화살표 함수에서 this 변경 (변경이 되지 않음)
arrowFunction.call(obj1); // undefined
arrowFunction.call(obj2); // undefined
이처럼 화살표 함수는 ES6에서 도입된 새로운 방식으로, 간단하고 간결한 문법으로 유연한 표현력을 높여주는 함수를 만들 수 있지만, 모든 상황에 화살표 함수를 사용할 수 있는 것은 아니므로, 주의해야할 점도 있다.