본문 바로가기

[ONEBITE-REACT] 021. JS 심화 - 배열 메서드 2. 순회와 탐색

codeConnection 2024. 3. 20.

이번 강의에서는 배열을 순회하고 탐색하는 메서드 5가지에 대해 학습한다.

forEach

개념

모든 요소를 순휘하면서 각각의 요소에 특정 동작을 수행시키는 메서드이다.

기본형

배열명.forEach(element, index, array)(function() {};)

배열의 모든 값을 하나씩 순회하면서 출력한다.
forEach에 콘솔에 출력하는 기능을 넣는다거나 특정 동작을 배열의 값마다 순회하면서 동작하게 하려면 파라미터로 위와 같이 콜백 함수를 넣으면 된다.

// 콜백 함수 (익명 함수)
배열명.forEach(ele, idx, arr)(function () {});

// 축약(화살표 함수)
배열명.forEach(ele, idx, arr)(() => {});

매개 변수 3가지

forEach의 매개변수로는 세 개를 담을 수 있다.

  • Current Value : 처리할 현재 요소 (필수)
  • index : 처리할 현재 요소의 인덱스 (선택)
  • array : forEach()를 호출한 배열 (선택)

첫번째 element는 반드시 써야 하고, 나머지는 선택적이다. 아래는 각 선택적 매개변수 두 가지를 사용했을 때와 사용하지 않았을 때의 차이다.

// 세 개 전부 사용
let arr1 = [1, 2, 3];

arr1.forEach(function(ele, idx, arr) {
  console.log(ele, idx, arr);
});
// 1 0 [1, 2, 3]
// 2 1 [1, 2, 3]
// 3 2 [1, 2, 3]

첫번째 연산
ele 매개변수에는 배열의 첫번째 요소인 1이 들어감. inx에는 요소 1의 인덱스인 0이 들어감. 그리고 이 배열 자체인 arr가 반환됨.
두번째 연산
반복 순회하여 다음 요소인 2, 다음 인덱스인 1, 배열 자체가 다시 반환됨.
세번째 연산
반복 순회하여 다음 요소인 3, 다음 인덱스인 2, 배열 자체가 다시 순환됨.

// arr 마지막 매개변수 생략, element와 index만 사용
let arr1 = [1, 2, 3];

arr1.forEach(function(ele, idx) {
  console.log(ele, idx);
});
// 1 0
// 2 1
// 3 2
// index와 arr 생략, 필수 매개변수인 element만 사용
let arr1 = [1, 2, 3];

arr1.forEach(function(ele) {
  console.log(ele);
});
// 1
// 2
// 3

예제

let arr1 = [1, 2, 3];

arr1.forEach((newArr) => console.log(newArr)); // 1 2 3 각각 출력

예제 2. 배열의 모든 값에 * 2를 하여 출력하라.

// 기본형(화살표 함수, 익명 함수 사용)
let arr1 = [1, 2, 3];

arr1.forEach((ele, idx) => {
  console.log(idx, ele * 2);
})
// 0 2
// 1 4
// 2 6
// 빈 배열에 push 메서드로 배열에 값 추가하기
let arr1 = [1, 2, 3];

const dobbledArr1 = [];

arr1.forEach((ele, idx) => {
  dobbledArr1.push(idx, ele * 2);
});

console.log(dobbledArr1); // [0, 2, 1, 4, 2, 6]
// 인덱스 하나-1번요소*2 하나, 인덱스 둘-2번요소*2...

includes

개념

배열에 특정 요소가 있는지 확인하는 메서드.
true나 false로 반환한다.

기본형

배열명.includes(찾을요소의값)

예제

let arr1 = [1, 2, 3, 4, 5];

console.log(arr1.includes(2)); // true

const include = arr1.includes(10);
console.log(include); // false

indexOf

개념

특정 요소의 인덱스(위치)를 찾아서 반환하는 메서드

기본형

배열명.indexOf()
  • 찾으려는 요소가 있을 때 : 해당 인덱스 반환
  • 찾으려는 요소가 여러개 일 때 : 가장 첫번째 요소의 인덱스 (앞에서부터 탐색하기 때문)
  • 찾으려는 요소가 없을 때 : -1 반환

예제

// 찾으려는 값이 있을 때
let arr = [4, 3, 2, 7, 6];

console.log(arr.indexOf(4)); // 0

// 찾으려는 값이 여러개 일 때
let arr = [1, 2, 3, 4, 4, 4, 4];

console.log(arr.indexOf(4)); // 3

// 찾으려는 값이 없을 때
let arr = [1, 2, 3, 4, 4, 4, 4];

console.log(arr.indexOf(10)); // -1

findIndex

개념

모든 요소를 순회하면서 콜백 함수를 반환하는 메서드이다.
특정 요소의 인덱스(위치)를 반환한다.

기본형

배열명.findIndex( () => {} );

findIndex 메서드의 매개변수의 요소를 찾아 배열을 순회하다가 해당 요소를 발견하면 그 값으로 {} 함수를 실행한다. 예제를 봐야 이해가 쉽다.

예제

let arr1 = [5, 4, 3, 2, 1];

const find = arr1.findIndex(function(element) {
    if (element === 4) return true;
})

console.log(find); // 1

find를 콘솔에 출력했을 때 true라는 불리언 값을 반환하라는 것이 아니라 있다면 출력하라는 것이다.

값이 없으면 -1을 출력한다.

let arr1 = [5, 4, 3, 2, 1];

const find = arr1.findIndex(function(element) {
    if (element === 4) return true;
})

console.log(find); // 1
let arr1 = [10, 4, 3, 2, 1];

const find = arr1.findIndex(function(element) {
    if (element % 2 !== 0) return true;
})

console.log(find); // 2 

위 조건문을 보면 element, 즉 arr1이라는 배열을 findIndex로 순회했을 때 나누기 2를 해서 나머지가 0이 아닌 것, 즉 홀수의 값을 찾았을 때 값을 반환하라 (return true)라고 되어 있다.
배열을 살펴보면 3이 가장 먼저 나오는 홀수이므로 인덱스로 2를 반환했다.

위와 같이 단순히 조건식으로만 이루어진 경우 조건식을 return하도록 함수를 간결하게 수정할 수 있다.

let arr1 = [10, 4, 3, 2, 1];

const find = arr1.findIndex((element) => element % 2 !== 0
);

console.log(find); // 2 

화살표 함수로 함수를 축약했고, 단순히 조건식에 맞으면 값을 return하는 식이기 때문에 중괄호와 return을 생략했다. 이전에 배운 내용이지만 헷갈리므로 더 공부하기에서 다시 다루겠다.

indexOf와 findIndex의 차이

메서드 비교방식 사용범위
indexOf 얕은 비교 단순히 배열의 값을 탐색
findIndex 깊은 비교 콜백 함수를 통해 배열 안의 객체도 프로퍼티로 탐색 가능

indexOf와 findIndex는 둘 다 특정 요소를 찾아 인덱스를 반환해주는 메서드로 같다.

차이가 있다면 사용방법인데, indexOf 메서드는 단순히 배열명.indexOf(찾을 요소)이고, findIndex 메서드는 배열명.findIndex(function() {})라는 콜백 함수를 받는다는 차이 정도로 보인다.

하지만 사용 방법에 차이가 있는 이유는 쓰임새도 다르다는 의미이다.

  • indexOf : 배열 안에 객체가 있는 경우 객체는 탐색하지 못함.
  • findIndex : 배열 안에 객체가 있는 경우에도 객체의 프로퍼티(key)를 이용해서 요소의 값을 찾아올 수 있음.
let ive = [
    {name: "장원영", group: "Ive"},
    {name: "안유진", group: "Ive"}
]

const wonYoung = ive.indexOf({name: "장원영", group: "Ive"});

console.log(wonYoung); // -1
// 0번 인덱스에 값이 있음에도 못 찾아오고 값이 없다고 -1을 반환함.

const wonYoung1 = ive.findIndex(
    (wonYoungName) => wonYoungName.name === "장원영"
) // 0 반환
// 만약 .group 프로퍼티가 Ive인 것을 찾으라고 하면 가장 먼저 있는 0번 인덱스를 출력함.

find

개념

모든 요소를 순회하면서 콜백 함수를 반환하는 메서드이다.
그런데 findIndex는 배열에서 요소의 인덱스(위치)를 반환했지만 find 메서드는 배열의 요소 그 자체를 반환한다.

기본형

배열명.find(() => {})

find 메서드는 매개변수로 콜백 함수를 받는다.

예제

let ive = [
    {name: "장원영"},
    {name: "안유진"}
]

let finded = ive.find((wonYoung) => wonYoung.name === "장원영"
)

console.log(finded); // {name: '장원영'}

더 공부하기

콜백 함수 (Callback function)

MDN, 프리코드캠프

개념

다른 함수에 전달되는 함수. 일종의 루틴이나 동작을 완료하기 위해 함수 내부에서 호출되는 함수를 말함. (함수 안에 있는 함수)

함수는 파라미터를 받는다.
자바스크립트에서 함수는 객체이다.
함수의 파라미터로 객체를 전달할 수 있다.

function print(callback) {
    callback();
}

위의 예제를 보면 print라는 함수의 파라미터로 callback을 받고 있고, 이 callback은 이미 선언된 함수이다. 즉 자바스크립트에서 함수는 다른 함수(객체)를 매개변수로 받을 수 있고 이를 콜백(Callback)이라고 한다. 그리고 위에서 callback()이라는 함수는 다른 함수의 파라미터로 전달된 함수이기 때문에 콜백 함수(Callback function)이라고 부른다.

필요한 이유

자바스크립트는 기본적으로 비동기(Asyunchronous) 프로그래밍 언어다. (비동기 프로그래밍에 대해서는 뒤에서 다룸)

기본적으로 코드 작성 순서대로 위에서 아래로 순차적으로 실행되지만 개발자의 의도에 따라 호이스팅 되는 함수도 있는 등 순서가 뒤바뀔 수도 있다.

따라서 개발자가 의도하지는 않았는데 B함수가 A함수보다 먼저 실행되어 Side effect를 발생할 수도 있다. 하지만 B함수가 A함수의 콜백 함수로 사용되었다면 B함수는 A함수에서 실행하라고 넣은 여러 함수들의 사이에서 작동 순서를 정할 수 있기 때문에 함수의 실행 순서를 보장할 수 있다.

예제

console에 massage라는 변수를 출력하고 싶다. 그런데 바로 출력이 되는 것이 아니라 3초 뒤에 출력하도록 하고 싶다.

const message = function() {
    console.log("이 메시지는 3초 뒤에 출력됩니다.");
}

setTimeout(message, 3000);

위 예제를 보면 message라는 변수를 선언한 뒤 함수를 넣는 함수 표현식이다. message라는 함수는 콘솔에 위와 같은 메시지를 출력하는 함수인데, message();로 실행한 것이 아니라 setTimeout이라는 자바스크립트 내장 함수를 사용하였고 매개변수로 massage 함수를 넣었다. 즉 message 함수가 setTimeout이라는 함수의 매개변수로 사용된 것이다. 그러면서 3000ms 뒤에 작동되게끔 되었으므로 이 massage 함수는 setTimeout의 콜백 함수로 사용되면서 작동 순서를 보장받게 된 것이다.

익명 함수 (Anonymous Function)

함수를 선언할 때 function myFunction() {}와 같이 함수의 이름을 지정하는 것이 일반적이지만 이는 함수 선언식이라 하고 값을 변수에 담는 함수 표현식으로 함수를 선언할 때는 함수의 이름을 생략한다. 어차피 변수의 이름이 곧 함수의 이름이기 때문이다.
익명 함수는 주로 콜백 함수에서 사용된다.

// 함수 선언식
funtion myFunction() {
    console.log("hello, world!");
}

// 함수 표현식
const myFunction = function() {
    console.log("hello, world!");
}

// 한 번 더 축약 : 화살표 함수
const myFunction = () => {
    console.log("hello, world!");
}

동기(synchronous) 프로그래밍 - 비동기(Asyunchronous) 프로그래밍

참고 블로그

'동기'라는 단어의 의미는 싱크, 즉 동기화에서 사용되는 그 '동기'이다. 즉 데이터를 주고 받는 사람 모두가 같은 화면, 같은 완료 상태가 되어야 동작이 완료된다는 의미이다. A와 B가 데이터를 주고 받는다면 A와 B 모두 연산이 끝난 상태로 동기화 되어야 하나의 작업이 완료된다.

반면 '비동기'는 A가 B에게 특정 요청을 보냈을 때 B는 그것을 연산하고 있고 결과를 보여주지 않았어도 A는 다른 작업을 할 수 있다. 그리고 B가 연산이 완료되어 A에게 데이터를 전송하여 완료되면 다른 작업을 시작할 수 있다.

자바스크립트는 기본적으로 비동기 프로그래밍을 따른다. 이유는 웹 페이지를 로드할 때 수많은 기능들이 로드되는데 사용자가 전부 로드될 때까지 기다리는 것은 쾌적한 사용경험을 제공할 수 없기 때문에 사용자가 이미지를 요청했고 서버가 이에 응답하기까지 시간이 걸리더라도 사용자는 웹 페이지에서 로드된 다른 기능을 이용할 수 있게 된다.

각자 장단점이 있다. 동기 프로그래밍을 사용하는 환경도 많다. 은행의 경우가 대표적이다. A가 B에게 이체를 했는데 데이터 처리하는 속도에 차이가 있어서 A는 돈을 보냈는데 B는 못 받은 상황이 연출된다면 이는 안정적인 금융 거래가 될 수 없다. 따라서 A가 이체를 했을 때 B가 완료되어야만 A도 이체가 완료됐다는 문구가 뜨는 동기 프로그래밍 방식을 채택하여야 한다.

화살표 함수 (Arrow Function)

함수 표현식에서 함수를 더 간결하게 => 를 넣어 표현할 수 있게 해주는 방법이다. 여러 단계가 있다.

// 함수 원형
function myFunction() {};

// 화살표 함수 1단계 : 함수 표현식으로 변경
const myFunction = function myFunction() {};

// 화살표 함수 2단계 : 화살표 추가, function 생략
const myFunction = myFunction() => {};

// 화살표 함수 3단계 : 익명 함수로 변경
const myFunction = () => {};
// 이미 함수 표현식으로 변수의 이름이 있기 때문에 함수명과 중복되므로 생략한다.

댓글