3월 17일 진행한 underbar 풀이를 정리해본다.
underbar?? 밑줄...?? 내가 처음 과제를 받자마자 든생각은 이랬다.
underbar는 배열 메서드가 브라우저에서 자체적으로 지원하지 않았을 시절,
보다 나은 방법으로 배열이나 객체를 다루기 위한 도구 모음집을 만들었는데
이를 라이브러리(Library)라고 불렀다.
따라서 이번 과제는 배열, 객체를 다루는 Underbar 라는 라이브러리를
직접 구현하면서 내장 메서드가 어떻게 동작하는지 원리를 학습.
여기서 collections가 나오는데, 이게 무엇이냐!!!
collection을 직역해보면 , '모음', '무리' 라는 뜻이다.
cs(컴퓨터 사이언스)에서는 '데이터(data, 자료)의 모음'이라고 생각할 수 있다.
우리가 배운 collection에는 객체, 배열 등등이 있다.
객체 - 서로 관련있는 데이터들(속성, property)을 "key-value" 형태로 "순서 없이" 모은 자료구조.
키(key)를 이용하여 데이터에 접근.
배열 - 데이터들(요소, element)을 "순서대로" 모은 자료구조.
요소의 위치를 통해 데이터에 접근.
collection의 각 데이터를 다루는 것은 매우 흔한 작업 중 하나이다.
예를 들어보면,
- 배열의 요소 중 가장 큰 값을 찾는 것
- 배열의 모든 요소의 합을 구하는 것
- 객체에 특정 속성의 이름(key)이 존재하는지 확인하는 것
위의 3가지를 예로들어 처리방법을 크게 정리해보면
- 배열의 요소 중 가장 큰 값을 찾는 것 => 현재 데이터가 가장 큰값인지 확인하여 계속 순회
- 배열의 모든 요소의 합을 구하는 것 => 현재 데이터를 누적값에 더하기
- 객체에 특정 속성의 이름(key)이 존재하는지 확인하는 것 => 현재 key가 원하는 값인지 확인
이처럼 비슷한 처리가 반복되기 때문에 이를 반복(iteration) 작업이라고 부른다.
자바스크립트는 이러한 반복작업을 위한 여러 수단들을 제공.
반복문(for, for of, for in, while)과 반복을 위한 내장메서드(arr.map, arr.filter)들이 대표적
Underbar 함수
- _.identity
전달인자(argument)가 무엇이든, 그대로 리턴하며
underbar의 기능 구현 및 테스트를 위해 재사용되는 함수
- _.slice
예시로 준 slice메서드를 가이드 삼아, 아래의 함수들을 구현하면 되었다.
처음에는 음... 그래... 뭐 그렇구나.. 하고 말았는데
아래의 함수들을 구현하려다보니 자세히 읽어보고 이해할 수 밖에 없었다.
- _.take
_.take는 배열의 처음 n개의 element를 담은 새로운 배열을 리턴
n이 undefined거나 음수인 경우에는 빈 배열을 리턴
n이 배열의 길이를 벗어나면?? 전체 배열을 얕은복사하여 새로운 배열 리턴
- _.drop
_.drop은 _.take와 반대로, 처음 n개의 element를 제외한 새로운 배열을 리턴
n이 undefined나 음수이면, 전체 배열을 얕은복사하여 새로운 배열 리턴
n이 배열의 길이를 벗어나면, 빈 배열 리턴
더 쉬운 방법이 있을텐데 중첩반복문까지 써가면서.... 다시 리팩토링 해야할것 같습니당
- _.last
_.last는 배열의 마지막 n개의 element를 담은 새로운 배열을 리턴
n이 undefined거나 음수면, 배열의 마지막 요소만을 담은 배열 리턴
n이 배열의 길이를 벗어날 경우, 전체 배열을 얕은복사하여 새로운 배열 리턴
- _.each
_.each는 collection의 각 데이터에 반복적인 작업을 수행.
- collection(배열 혹은 객체)과 함수 iteratee(반복되는 작업)를 인자로 전달받음.
여기서 iteratee는 함수의 인자로 전달되는 함수이므로 callback 함수 - collection의 데이터(element 또는 property)를 순회하면서
- iteratee에 각 데이터를 인자로 전달하여 실행
- 배열 arr을 입력받을 경우, iteratee(ele, idx, arr)
- 객체 obj를 입력받을 경우 iteratee(val, key, obj)
- 이처럼 collection의 모든 정보가 iteratee의 인자로 잘 전달되어야
- 모든 경우를 다룰 수 있게 된다.
- _.filter
_.filter는 test 함수를 통과하는 모든 요소를 담은 새로운 배열 리턴
test(element)의 결과(return 값)가 truthy일 경우, 통과
test 함수는 각 요소에 반복 적용
- _.uniq
_.uniq는 주어진 배열의 요소가 중복되지 않도록 새로운 배열 리턴
중복 여부의 판단은 엄격한 동치 연산(===)을 사용해야함.
입력으로 전달되는 배열의 요소는 모두 primitive value라고 가정
- _.map
_.map은 iteratee(반복되는 작업)를 배열의 각 요소에 적용한 결과를 담은 새로운 배열 리턴
배열의 각 요소를 다른것(iteratee의 결과)으로 매핑.
- _.reduce
reduce는
- 배열을 순회하며, 각 요소에 iteratee 함수를 적용,
- 그 결과값을 계속해서 누적(accumulate)
- 최종적으로 누적된 결과값을 리턴
_.reduce는 반복해서 값을 누적하므로, 이 누적되는 값을 관리
따라서 정리한 형태는
iteratee(acc, cur, idx, arr)
acc는 '이전 요소'까지의 반복 작업의 결과로 누적된 값
cur은 반복작업을 수행할(아직 수행안함) 현재의 요소
하지만, '누적값을 어디서 시작하는가'를 해결하기 위해서는
initVal을 주어 초기값을 전달해준다.
따라서 최종적인 형태는
_.reduce(arr, iteratee, initVal)
iteratee(acc, cur, idx, arr)