개발일기
[딥다이브] 26. ES6 함수의 추가 기능 본문
이번단원은 일단 분량도 짧은 편이고 화살표함수나 매개변수 기본값 등 알고있는 개념을 말하는거라 호로록 읽을 거라고 생각했지만... 중간중간 또 동태가 되어버렸다
암튼 요약을 하자면 이전 ES5에서 사용하던 일반함수와 ES6에서 추가된 함수 종류들의 차이점과 사용법을 설명하는 내용이다.
ES5에서는 일반함수와 생성자함수를 정의하는 것에 구분이 없었다.
그래서 함수를 정의해놓고 일반함수로 호출sum(); 하면 일반함수인거고,
new를 붙여 생성자함수로 호출하면new sum(); 생성자함수인 것.
그리고 메서드도 냅다 걍 일반함수로 돌리고 있었음
유연하다는 장점이 있으나 일반함수나 메서드로 사용할 때는 사용하지않는 constructor나 prototype이 생성되어 굳이 사용도 안하는데 얘네를 생성할 필요가...? 이렇게 되버린다. 그러니까 쓸데없이 생성되어 용량차지함.
그래서 ES6에서는 메서드와 화살표 함수가 추가되었다!
1. 메서드
일단 메서드는 객체에 바인딩된 함수이다. ES6에는 프로토타입과 constructor가 없는 메서드 전용 함수를 설정했는데 그건 그냥 객체 안에서 메서드 축약표현을 사용하면 메서드가 되는 거다. foo() {return this.x}
이 ES6메서드는 객체.메서드.hasOwnPrototype('prototype') 일케 찍으면 false가 뜨고(prototype이라는 프로퍼티 있냐 - 아니요) new 객체.메서드() 일케하면 에러뜸
메서드에서는 super라는 키워드를 사용할 수 있는데, 얘는 메서드가 바인딩 된 객체의 프로토타입을 가리킨다. 이 super는 객체의 [[HomeObject]]라는 내부슬롯을 사용하여 참조할 수 있는데, 메서드가 아닌 함수는 [[HomeObject]]가 없기때문에 super를 사용할 수 없다!
** 메서드 공부하면서 이해가 안됐던건 프로토타입을 안쓴다고 해서 프로토타입을 없앤 ES6메서드를 만들었는데, super로 프로토타입을 사용한다고? 이렇게 생각했는데 다시 읽고 바인딩된 객체의 프로토타입과 연결한다는 것을 이해했다. 그런데 또 의문점이 들었던 건
왜 객체의 프로토타입을 사용하는걸까 메서드의 프로토타입은 없애면서? 재사용때문에 프로토타입을 사용하는 것이라면 그냥 객체에 일반함수로 정의해서 그 함수의 프로토타입을 재사용할 객체와 바로 연결하면 안되나? 였다.
프로토타입이라는 단어로 계속 설명하니까 내가 이 단어에만 꽂혀서 메서드라는 함수를 사용하는 이유에 대해서는 생각을 못하고 있었던 것 같다. 내가 생각한 이유는 메서드는 객체에 바인딩 된 함수인데, 이 함수에 따로 프로토타입을 만들면 굳이 객체에 넣을 필요가 없기 때문이 아닐까 싶다.
2. 화살표 함수
화살표 함수는 일반함수로 호출할 때 사용하며 메서드와 마찬가지로 프로토타입과 constructor가 없다. 이 화살표함수는 매개변수가 하나이면 ()를 생략할 수 있고 리턴값이 표현식이면 {return }을 생략할 수 있고 어쩌구저쩌구하지만 화살표함수의 핵심은 this인 것 같다.
이 화살표 함수가 만들어진 건 콜백함수에서의 this 불일치 문제를 해결하기 위함이다. 예를들어 ES5에서 클래스 내부에서 프로토타입 메서드를 만들고 그 내부에 map을 사용하여 map의 매개변수로 일반함수를 콜백함수로 넣어보자. 이 두 함수에서 사용하는 this는 같지 않다. 전자의 this는 생성한 인스턴스가 될 것이고, 후자의 this는 undefined가 된다.
👉 일반함수에서 this를 사용하면 this는 전역객체를 가리키지만, 클래스안에서는 모두 strict mode가 적용되고 이 strict mode에서 this는 undefined를 가리키기때문
이렇게 this가 가리키는 값이 달라서 ES5에서는 뭐 this를 따로 변수로 만들어서 콜백함수에 넘겨줬다가 두번째 매개변수에 보내줬다가 한다.
하지만 ES6에서는 화살표 함수를 사용하면 함수 자체의 this를 가지지 않고, 상위 스코프의 this를 그대로 참조한다.
주의해야할 점은 메서드나 프로토타입 객체의 프로퍼티로 화살표함수를 사용한다면 this는 상위 스코프의 this를 사용하는데 여기서 상위 스코프는 전역객체이기 때문에 this 불일치가 일어난다. 메서드나 프로토타입 객체에서 화살표함수를 사용하는 것은 맞지 않다. 그런데 왜 상위스코프가 전역객체일까? 바인딩된 객체가 아니라..? 바인딩된 객체가 상위 스코프 아닌가 ㅠ
화살표 함수에서는 super와 arguments도 자체 바인딩이 없고 상위 스코프를 참조한다.
super를 참조하면 constructor의 super를 참조하고(?..)
arguments를 참조하면 상위 함수의 인수목록을 받는데 사실상 이건 받아도 쓸데가 없는 듯..
(여기부터는 함수 정의 방법이 아니라 ES6에 추가된 함수관련 사항들)
3. Rest 파라미터
인수가 정해지지 않은 함수에서 인수들을 배열로 받으려면 ...을 붙여서 텍스트 아무거나 붙이면 Rest파라미터가 된다.
나는 작업을 리액트를 많이 사용하는데, 컴포넌트도 사실 함수이므로 컴포넌트의 prop(파라미터)에서도 이렇게 사용할 수 있다.
const Button = ({ label, ...props }) => {
return <button {...props}>{label}</button>;
};
// 사용 예:
<Button label="Click me!" onClick={() => alert("Clicked!")} style={{ fontSize: '16px' }} />
4. 매개변수 기본값
매개변수에 기본값을 설정해 줄 수 있다. 인수를 전달하지 않으면 기본 값으로 적용되는데, 이것도 컴포넌트 프롭스에 기본값을 설정해주는 방식으로 리액트에서도 많이 사용하고 있다.
.
공부를 하면서 꼬리에 꼬리를 무는 질문도 많고, 혼자서 공부하다보니 답을 못찾을 때도, 지쳐서 이해하고 싶지 않은 것도 있다. 내일 스터디하기 전까지 더 알아보고 그래도 모르는 건 또 스터디 하면서 물어봐야지.
이번에는 실제로 업무하면서 사용하는 개념이라 클래스 프로토타입 이런 것보다 쬐.. 끔 더 흥미롭게 읽었던 것 같다.
이번에 정리하는 방식을 바꿔서 내가 누군가에게 설명한다는 느낌으로 했는데 이전보다 전체적으로 이해하는건 좋지만 시간이 생각보다 많이 걸린다... 이렇게 한번하고 담에는 못할까봐 무섭지만 그래도 화이팅하자😇
'JavaScript' 카테고리의 다른 글
Ajax와 Axios와 fetch 정리 (0) | 2023.06.16 |
---|---|
콜백함수, Promise, async/await을 정리해보자 (0) | 2023.04.18 |
[새싹 프론트엔드] 고차 함수 정리(map, filter, reduce, forEach) (0) | 2023.01.01 |
[새싹 프론트엔드] GRS80TM좌표계 -> WGS84좌표계 변환하기 (0) | 2022.11.26 |
[새싹 프론트앤드] JSON 데이터 통신 (0) | 2022.11.15 |