🐕 과제를 하다가...
underbar라는 과제가 있는데 배열 내장 메서드 없이
배열 내장 메서드를 구현하는 내용이었습니다.
근데 전 length 프로퍼티도 사용하면 안되는 줄 알고
이걸 length 없이 어떻게 구현할까 고민하다가
결국 이터러블 프로토콜을 이용해서 직접 만들면되지않나? 라는 결론에 도달했어요
👻어케 함
다행히도 정적메서드는 사용해도 오류가 안 나길래 썼는데..
(생각해보면 정적메서드도 되는데 length를 막아놨다고 생각하는 거 자체가 이상하긴함)
그러면 맨 처음 생각나는 선택지는
while문을 만들어서 무한정으로 값을 올려주는
let idx = 0
while(arr[idx] !== undefined) {
idx++
}
이런 선택지를 고려할 수 있을 것입니다.
하지만 이 방식에는 치명적인 문제점이 있어요
흔치는 않겠지만 배열의 요소에 의도적으로 undefined가 할당되어있는 경우
굉장히 이상하게 동작할텐데 그걸 예외처리해줄 방법도 딱히 없으니까요!!
결국 가장 확실한건 이터레이터와 넥스트메서드를 사용하는거라고 생각했습니다.
_.each = function (collection, iteratee) {
if (Array.isArray(collection)) {
let idx = 0;
let areYouDone = collection[Symbol.iterator]();
let doneBoolean = false;
while (!doneBoolean) {
const iResult = areYouDone.next();
doneBoolean = iResult.done;
if (doneBoolean) return;
let iValue = iResult.value;
iteratee(iValue, idx, collection);
idx++;
}
} else {
for (let key in collection) {
iteratee(collection[key], key, collection);
}
}
// TODO: 여기에 코드를 작성합니다.
};
따라서 이렇게 구현을 했는데 사실 처음부터 이런 구조였던게아닙니다.
첫번째 주의 사항
done 프로퍼티의 값을 받아오려면 next() 메서드를 호출해야하고
next()메서드는 어디서 호출되었든 호출되는 순간
다음 요소로 전진해버리기 때문에
한 반복에서 딱 한번만 next()메서드를 사용하고
그 값을 변수에 저장한 뒤 적절하게 사용해줄 필요가 있습니다.
따라서 iResult변수에 next() 메서드의 호출 결과(이터레이터 리절트 객체)를 담아준 뒤
그 값들을 활용해서 while문의 종료조건으로도 사용하고..
콜백의 인자로도 사용하고... 다 해주면 됩니다.
두번째 주의사항
done 프로퍼티의 밸류가 true로 바뀌는 시점은
마지막 요소를 만난 다음 next() 메서드입니다.
let arr = [1, 2, 3, 4, 5];
let a = arr[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
따라서 위 코드의 출력결과를 생각해보면 쉽습니다.
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }
배열의 길이는 5인데 next메서드는 총 6번을 호출해야
done이 true로 바뀝니다.
그럼 마지막 호출일땐 코드를 실행하지않고 끝내줘야 정상적으로 동작할거란 예상이 가능하죵
let idx = 0;
let areYouDone = collection[Symbol.iterator]();
let doneBoolean = false;
while (!doneBoolean) {
const iResult = areYouDone.next();
doneBoolean = iResult.done;
if (doneBoolean) return;
let iValue = iResult.value;
iteratee(iValue, idx, collection);
idx++;
}
따라서 이렇게 코드를 작성하면
아주 멋진 나만의 forEach문이 완성되지만
원본 forEach문이 더 좋으니까 쓸모는 없겠네요 감사합니다.
'cheetsheet' 카테고리의 다른 글
자바스크립트로 구현하는 디바운싱 예제(trailing edge) (0) | 2023.04.22 |
---|---|
node-sass 설치 에러 해결 방법과 원인.. (0) | 2023.04.16 |
콜백으로 준식 지옥을 만들어보자 (8) | 2023.03.16 |
reset.css 인풋,버튼 태그의 배경 바꾸기와 placeholder 글자 색 바꾸기 (0) | 2023.03.04 |
도커를 사용해보자 아주 멋지게..Docker.... (0) | 2023.02.24 |