forEach()가 아무것도 반환하지 않는다는 것을 깨달은 순간.

Javascript ES5의 forEach() 메서드와 저는 지난 주까지 두 개의 배열을 가져와 공통 항목이 포함되어 있는지 여부를 결정하는 이 간단한 함수 안에 구현하려고 할 때까지 꽤 잘 지내왔습니다.

두 개의 forEach() 루프 중 하나가 작업 수행을 거부했습니다.



그래서 저는 두 개의 테스트 어레이로 시작했습니다.

const animals = ["lion", "dog", "kangaroo"];
const pets = ["hamster", "parrot", "dog", "cat"];

haveCommonItems(animals, pets); // should return "true"


분명히 두 입력에는 모두 "dog"이 포함되어 있으므로 호출되는 내 함수는 이 경우 true을 반환할 수 있어야 합니다. time complexity optimization 을 위해 Javascript ES5의 false 메서드를 사용하여 두 개의 독립 루프(중첩 루프 대신)를 제공하기로 결정했습니다.

const haveCommonItems = (array1, array2) => {
  array1.forEach(
    // converts array1 items into properties
    // returns an object that has those properties
  );

  array2.forEach(
    // checks if array2 items equal to properties on object created from first loop
    // returns a boolean
  );
}


내 첫 번째 Array.prototype.forEach() 루프는 다음과 같이 예상 개체를 생성하여 작업을 수행합니다.

const haveCommonItems = (array1) => {
  let obj = {};
  array1.forEach(item => !obj[item] ? obj[item] = true : null);
  console.log(obj);
};

haveCommonItems(animals); // logs {lion: true, elephant: true, dog: true, kangaroo: true}


두 번째 forEach()이 나왔을 때 상황이 혼란스러워지기 시작했습니다. 함수를 실행할 때 나는 결코 일어나지 않은 forEach()을 얻을 것으로 기대했습니다. 대신 true이 있습니다.

const haveCommonItems = (array1, array2) => {
  let obj = {};
  array1.forEach(item => obj[item] ? null : obj[item] = true);

  array2.forEach(item => {
    if (obj[item]) {
      return true;
    }
  });

  return false;
};

haveCommonItems(animals, pets); // returns "false" (me: "c'mon gimme a break!")


분명히 내 false이 실제로 어레이 자체를 통해 루프를 돌지 않았거나 그랬지만 이기적이고 아무 것도 돌려주지 않는 것처럼 보였습니다.

나는 후자에 대해 옳았다.

소위 루프 내부에서 실제로 무슨 일이 벌어지고 있었습니까?



저는 MDN web docs으로 뛰어들어 약간의 조사를 했습니다. 이전에는 거의 주의를 기울이지 않았던 이 한 가지 주요 기능만 알아냈습니다.

forEach()는 항상 정의되지 않은 값을 반환하며 연결할 수 없습니다.



그리고

예외를 throw하는 것 외에는 forEach() 루프를 중지하거나 중단할 수 있는 방법이 없습니다.


array2.forEach()이 내 오랜 친구 forEach() 루프에서 작업을 완전히 인수하기 위해 거기에 있다는 잘못된 인상을 받았습니다. 실제로 for()은 값을 반환하지만 forEach()에 의해 생성된 범위 내에서만 반환되는 callback 함수를 받습니다. 즉, forEach() 내부의 return 문은 값을 범위 밖으로 가져오거나 함수를 종료한 적이 없습니다. 그 값을 callback으로 반환한 다음 나머지 배열을 계속 탐색한 다음 forEach()을 보스 undefined으로 반환했습니다.

이 시점에서 내 함수 haveCommonItems()(haveCommonItems() 값을 얻을 때)은 그 undefined(불쌍한 꼬마!) 내부에서 무슨 일이 일어났는지 전혀 몰랐습니다.

예, 그 AHA 순간이 여전히 지속되는 동안, 저는 이에 대한 약간의 해결책을 생각해 냈습니다.

const haveCommonItems = (array1, array2) => {
  let obj = {};
  array1.forEach(item => obj[item] ? null : obj[item] = true);

  let found = false;
  array2.forEach(item => {
    if (obj[item]) {
      found = true;
    }
  });
  return found;
};

haveCommonItems(animals, pets); // returns "true" (me: "you better do!")


Javascript ES5의 forEach() 메서드는 항상 false을 반환하지만 부작용을 실행합니다. 이러한 이유로 항목이 forEach() 속성 중 하나와 같으면 undefined의 값을 found으로 설정할 수 있습니다. (true은 예외가 발생하지 않는 한 중지하거나 중단할 수 없기 때문에 배열이 끝날 때까지 계속 반복됩니다.)

그래서 저는 다시는 obj 루프에 속지 않기를 바라며 이것을 기록합니다.


업데이트됨



아래 개발자 동료의 멋진 추천 덕분에 다음과 같이 코드 수준을 높일 수 있었습니다.

const haveCommonItems = (array1, array2) => {
    const array1set = new Set(array1);
    return array2.some(item => array1set.has(item));

haveCommonItems(animals, pets); // returns "true"
}


다시 한 번 감사합니다!

좋은 웹페이지 즐겨찾기