이터레이터,,, 제너레이터,,, 이터러블,,, 이터레이터,,, 이터러블,,, 🤯

✏️ 새롭게 배운 것

일급 객체 (first class citizen)

예전에 구글링하다가 일급 객체의 존재를 알게 됐다. 하지만 일급 객체가 뭔지, 왜 함수가 일급 객체인지는 오늘 새롭게 알게 됐다!
일단 일급 객체는 JS에서만 사용되는 용어가 아니다. 컴퓨터 프로그래밍 언어 디자인에서 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다고 한다. 여기서 일반적으로 적용 가능한 연산이란 것은 함수에 매개변수로 넘기기, 수정하기, 변수에 대입하기와 같은 연산들을 말한다. 일급이라고 해서 무슨 특별한 기능을 한다는 것이 아니라, 사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻한다. Robin Popplestone이라는 사람이 후에 명확한 기준을 제시했다.

  • 모든 일급 객체는 함수의 실질적인 매개변수가 될 수 있다.
  • 모든 일급 객체는 함수의 반환값이 될 수 있다.
  • 모든 일급 객체는 할당의 대상이 될 수 있다.
  • 모든 일급 객체는 비교 연산을 적용할 수 있다.

일급 함수

JS에서 function은 Object를 상속 받아 사용하는 prototype 객체이다. 즉, function도 Object라는 것이다! 이 말은 JS에서 function 또한 일급 객체이며, 일급 함수라는 말이다. 당연하게도 함수 또한 위의 기준을 충족한다. 함수가 함수의 매개변수, 반환값이 될 수 있고, 함수를 변수에도 할당할 수 있다. 평소에 아무렇지 않게 함수를 변수에 할당해서 쓸 수 있었던 게 다 일급 함수였기 때문이다!
그냥 사용이 자유롭다고 생각하고 넘기면 되는거 아냐? 싶지만 잘 알아둘 필요가 있다. 바로 JS에서 함수가 일급 객체이기 때문에 가능한 것이 있기 때문이다.

  • 콜백 패턴을 사용할 수 있다.
  • 함수를 반환하는 고차함수를 만들 수 있다.
  • 클로저를 사용해 커링과 메모이제이션이 가능하다

클로저

일급 함수여서 클로저를 사용할 수 있다? 🤔 무슨 말인지 감이 잘 안오지만 천천히 살펴보자.
사실 클로저 자체가 딱 뭐라고 말하기 힘든 개념인 거 같다. 누구는 환경이라고 하고, 누구는 함수라고 하고,,, MDN에서는 이렇게 정의하고 있다.

클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.

더 무슨 말인지 모르겠다. 함수와 렉시컬 환경과의 조합? 이 말을 이해하려면 스코프 얘기를 다시 꺼내야한다. 간단하게 복기해보자면 스코프는 크게 전역, 지역 스코프로 나눌 수 있다. 전역 스코프에 선언된 변수들은 코드 어디에서든지 참조 가능한 반면, 지역 스코프에 선언된 변수들은 해당 영역과 하위 영역에서만 참조 가능하다. 이제 스코프와 일급 함수를 생각하면서 클로저에 대해 알아보자.

쉬운 예시를 들어보자면, 사과가 몇 갠지 밖에 말하지 못하는 머쓱이의 집에 사과가 5개 있다고 가정해보자. 머쓱이 친구들은 머쓱이네 집에 들어가지 못하기 때문에 머쓱이네에 사과가 몇 개 있는지 알 수 없다. (= 전역에서 지역 변수를 참조할 수 없다!) 하지만 방법이 있다. 바로 외출한 머쓱이에게 사과가 몇 개 있는지 물어보는 것이다. 그럼 머쓱이는 친절하게 사과의 개수를 알려준다.

여기서 머쓱이함수의 반환값으로써 반환된 내부함수를 의미하고, 사과 5개머쓱이가 선언됐을 때의 스코프인 렉시컬 환경을 의미한다. 머쓱이는 외출해서도 사과 5개의 존재를 알고 있다.
결론! 여기서 머쓱이가 바로 클로저다! 결국 클로저는 내부함수가 반환되었을 때 내부함수가 선언되었던 환경인 스코프를 기억해서 자신이 선언됐을 때의 환경(스코프) 밖에서도 그 환경에 접근할 수 있는 함수를 말한다.
물론 머쓱이가 집 밖에서도 사과 개수를 알고있는 이유(현실 세계에서는 당연한거지만,,,)를 설명하려면 스코프 체인에 대해 더 알아봐야한다. 🤯

이터레이션

ES6부터 기존의 for문 대신 간편하게 사용하는 for...of. 당연히 내부적으로 초기화식, 조건식, 증감식이 구현되어 있을 줄 알았는데 아니었다! 일반 for문은 예를 들어 i를 설정해서 인덱스로 array의 요소에 접근하는 방식이었는데, 같은 방식으로 set과 map은 순회할 수 없다. 반면, for...of는 array는 물론, set과 key의 각 요소에 접근할 수 있는 걸로 보아 for...of의 작동방식은 기존 for문과는 다르다는 것을 알 수 있다. 그렇다면 내부적으로 어떻게 구현되어있는걸까?

이터레이션 프로토콜

먼저 이터레이션 프로토콜은 데이터 컬렉션(Array, Set, Map)을 순회하기 위한 프로토콜이다. 프로토콜을 준수한 객체는 for...of으로 순회할 수 있다. 이터레이션 프로토콜에는 이터러블 프로토콜이터레이터 프로토콜이 있다.

이터러블

이터러블은 이터러블 프로토콜을 준수한 객체다. 이터러블은 무조건 Symbol.iterator 메소드를 가지고 있어야한다. 이 Symbol.iterator는 또 Symbol.iterator를 그대로 갖고 있다. well-formed iterable은 자기자신을 반환하는 Symbol.iterator를 가지고 있는 이터러블을 말한다.

이터레이터

이터레이터는 이터레이터 프로토콜을 준수한 객체다. 이터레이터 프로토콜은 next 메소드를 가지고, next 메소드를 호출하면 이터러블을 순회하며 value, done 프로퍼티를 갖는 이터레이터 결과 객체를 반환하는 것이다. well-formed iterator는 어디에서든 Symbol.iterator로 이터레이터를 만들었을 때 이전까지 진행되어있던 자기의 상태에서 계속해서 next()를 할 수 있는 이터레이터를 말한다.

🔥 더 공부해 볼 것

스코프 체인과 클로저의 활용

스코프 체인이 어떻게 일어나는지, 그리고 클로저를 이해는 했는데 어떻게 사용해야할 지 아직 잘 모르기 때문에 더 공부해보려고 한다.

Symbol.iterator

솔직히 뭔지 잘 모르겠다 ㅋㅋㅋ,,, 자세하게 찾아봐야 될 것 같다.

generator

아직 이해를 못했고,, 더 쓰면 글이 너무 방대해질 거 같아서 다음에 다시 알아보려고 한다,,

마무리

클로저에 대해서 얼렁뚱땅 넘어갈 뻔 했는데 다행히 일급함수를 다루면서 다시 복기할 수 있는 기회가 됐다. 렉시컬 환경이 뭔가 싶었는데 쉬운 예시로 생각해보니깐 이해할 수 있었다. 그리고 검색할 때마다 모던 자바스크립트 Deep Dive가 나오는데 이제 승복해야겠다. 저 책을 사야겠다 ㅋㅋㅋㅋㅋ
그리고 저번주보다 글 쓰는게 0.001% 쉬워졌다! 강의 자료 + 구글링 + 찾아보면서 내가 이해한 점을 간략하게 쓰려고 하니깐 뭔가 부담이 아주아주 약간덜한 것 같다.
이터레이터, 이터러블은 글에 써놓긴 했지만 솔직히 완전히 이해하지 못했다. 아직 강의가 좀 남아있으니깐 더 들으면서 찾아봐야겠다

출처

0개의 댓글