JS 콜백과 배열

최승두·2023년 12월 11일
0
post-thumbnail

JS의 핵심! 함수와 배열 메서드

배열 메서드의 일부를 배울텐데, 배열 메서드 안에는 함수가 들어가야 한다.
자바스크립트를 하면서는 필수라고 보면 되는 부분이다. 시간을 들여 충분히 이해하자.
외에도 화살표 함수가 있는데 언제나 배열 메서드와 함께 쓰인다.


forEach

기본 개념

기본적으로 forEach는 배열 안의 아이템 각각에 대해 함수와 코드를 한 번씩 실행한다.
그래서 어떤 함수를 넣든 상관없이 함수가 아이템별로 한 번씩 호출되고.
각각의 아이템이 함수에 자동으로 전달된다.

const numbers = [1,2,3,4,5,6,7,8,9,10];

function print(element) {
  console.log(element);
}
print(numbers[0]); // 1, 직접 출력하기
print(numbers[1]); // 2

numbers.forEach(print); // 1,2,3,4,5,6,7,8,9,10

하지만 이미 정의한 함수를 forEach로 전달하는 것은 일반적이지 않다.

const numbers = [1,2,3,4,5,6,7,8,9,10];

numbers.forEach(function (el){
	console.log(el);
}); // 1,2,3,4,5,6,7,8,9,10

대부분은 이렇게 익명함수로 사용하는 방법을 쓴다.
요즘은 for of를 사용하지만, 예전에 많이 쓰기도 했고
가장 쉬운 내부에 함수를 사용하는 배열 메서드였다.


MAP

콜백 함수를 수령해서 배열의 요소당 1번씩 실행한다는 점에서 forEach와 유사하다.
하지만 큰 차이점이 있는데, 그 다음에 그 콜백의 반환 값을 이용해서
새로운 배열을 생성한다는 것이다.

기본 예시

const numbers = [1,2,3,4,5,6,7,8,9,10];

const doubles = numbers.map(function(num) {
	return num * 2;
}); // [2,4,6,8,10,12,14,16,18,20];

numbers는 그대로 있고,
doubles라는 새로운 배열이 만들어진다.

그래서 보통 데이터의 일부만 가져온다거나, 두 배로 늘린다거나 할 때 필요합니다.


화살표 함수

더 간결한 함수 표현식!
화살표 함수든 일반 함수 표현식이든 단독으로 만들 순 없다. 변수가 꼭 필요하다

기본

예시..

const add = (x, y) => { return x + y; }

const rollDie = () => {
  return Math.floor(Math.random() * 6) + 1;
} // 매개변수가 없는 함수는 빈괄호로 표현

const square = num => { 
  return num * num;
} // 매개변수가 한 개라면 괄호 생략이 가능하다 (1개만)

function을 생략하고 화살표를 파라미터 뒤에 넣었다.

더욱 간결하게 (암시적 반환)

암시적 반환의 예시

const rollDie = () => ( // 괄호로 바꿨다
  Math.floor(Math.random() * 6) + 1; // return 생략
  )

아래와 같이 암시적 반환은 괄호까지도 생략 가능하다.

const add = (a,b) => a + b; // 괄호, 리턴 모두 생략

주의할 점

반환할 표현식,값이 무조건 하나여야 한다.

const newMovies = movies.map(function (movie) {
  return `${movie.tittle} - ${movie.score / 10}`;

// 두 코드는 같다.  
  
const newMovies = movies.map(movie = (`${movie.tittle}-${movie.score /10}`
)) 

이렇듯 화살표 함수는 코드를 더욱 간결하게 만들고
함수를 다른 함수나 메서드에 전달할 때 자주 사용하게 된다.


setTimeout과 setInterval

이 함수들에는 콜백 함수를 전달해줘야 하지만, 그렇다고 배열 메서드는 아닌 함수들이다.
추후 날짜로 실행을 연기하거나 작업 일정을 정하는 역할을 하는 함수들이다.

다른 언어에서는..
print "hello..."
sleep(3000) / pause(3000) 같은 특정 메서드를 사용해서 작동시킨다.
print "are you still there?"

하지만 JavaScript에서는 조금 다르게 작동한다.

setTimeout

setTimeout(() => {
	console.log("HELLO!!");
},3000) // 3초 후에 함수 실행

첫 번째 자리에는 콜백 함수를 넣어줘야한다. (다른 값을 넣으면 실행 안됨)
두 번째 밀리 초 숫자의 시간이 흐른 후에 함수를 1회 실행하는 것.

console.log("HELLO"); 1st

setTimeout(() => {
	console.log("...are you still there?"); ...after 3s / 3rd
},3000) // 3초 후에 함수 실행

console.log("GOOD BYE!"); 2nd

hello와 good bye가 실행되고 3초 뒤에 are you still there?이 실행된다.
끝!

setInterval

setInterval(() => {
	console.log(Math.random())
}, 2000) // 매 2초마다 계속 반복해서 함수 호출

setInterval을 종료하는 함수 clearInterval

setInterval 함수는 사용할 수 있는 ID를 반환한다.
이 함수를 쓰려면 setInterval의 반환값을 저장하기만 하면 된다!
(호출할 때마다 이 함수는 설정해놓은 인터벌에 해당하는 ID를 반환한다.)

const id = setInterval(() => {
	console.log(Math.random())
}, 2000) // 매 2초마다 계속 반복해서 함수 호출
---------------------------------------
<console 창에> clearInterval(id); // 종료!

Filter

쉬운예시

const numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

numbers.filter(n => {
	return n < 10;
}) // [1,2,3,4,5,6,7,8,9]

이 처럼, 주어진 조건에 맞는 요소들을 걸러내어 새로운 배열을 생성한다.
(같은 조건으로 map 함수를 쓰면 true,false로 출력된다)

다른예시

const movies = [
  {
    title: 'Amadeus',
    score: 99,
    year: 1984
  },
  {
    title: 'Sharknado',
    score: 35,
    year: 2013
  },
  ...
  ...
  ...
  {
    title: 'Parasite',
    score: 95,
    year: 2019
  },
]

  const goodMovies = movies.filter(movie => {
  	return movie.score > 80;
  }); // 81점 이상인 영화들만 필터링해서 출력!
  
  암묵적변환
  const goodMovies = movies.filter(m => m.score > 80);
  map과 함께 사용
  const goodTitles = goodMovies.map(m => m.title);
  // title만 출력되게 만듦
  filter,map 한 번에 사용하기
  movies
    .filter(m => m.score > 80)
    .map(m => m.title);
  
  // 최신영화
  const recentMovies = movies.filter(m => m.year > 2000);

위 처럼 여러 필터링 예시를 만들 수 있다

filter 와 map 차이점

filter 함수는 주어진 조건에 맞는 요소들을 걸러내어 새로운 배열을 생성하고, map 함수는 각 요소를 변환하여 새로운 배열을 생성합니다. 두 함수는 서로 다른 용도를 가지고 있으며, 사용 시 목적에 따라 선택해야 합니다.


SOME과 EVERY 메서드

한 쌍으로 불리는 둘은 아주 비슷한데, 불리언 메서드라서 참이나 거짓 값을 반환한다.

every

const exams = [90,80,98,78,77,81,89];
exam.every(score => score >= 75); // true

모두 참이면 true를 반환한다. 하나라도 false면 false를 반환한다.

some

const movies = [
  {
    title: 'Amadeus',
    score: 99,
    year: 1984
  },
  {
    title: 'Sharknado',
    score: 35,
    year: 2013
  },
  ...
  ...
  ...
  {
    title: 'Parasite',
    score: 95,
    year: 2019
  },
]

movies.some(movie => movie.year > 2015); // true

every와 똑같이 작용하지만, 최소 한 개 이상이면 true를 반환한다.


REDUCE

악명 높은 reduce 함수.
배열을 가져다가 점차 줄여가면서 마지막에는 결국 하나의 값만 남긴다.

기본 예시

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 15

다른 예시

const prices = [9.99, 1.50, 19.99, 49.99, 30.50];

/* 기본 for of 문
	let total = 0;
	for (let price of prices) {
  		total += price;
	}
	console.log(total); // 111.97 
*/ reduce 함수 사용

const total = prices.reduce((total, price) => {
	return total + price;	
});
total // 111.97

reduce의 첫 번째 매개변수는 보통 accumulator라고 부르는데 합계이다. total로 대체
두 번째 매개변수는 배열에 있는 각각의 개별 요소를 나타낸다. price로 대체

영화 배열로 reduce 응용

const movies = [
  {
    title: 'Amadeus',
    score: 99,
    year: 1984
  },
  {
    title: 'Sharknado',
    score: 35,
    year: 2013
  },
  ...
  ...
  ...
  {
    title: 'Parasite',
    score: 95,
    year: 2019
  },
]

const bestMovie = movies.reduce((bestMovie,currMovie)=>{
    if (currMovie.score > bestMovie.score) {
        return currMovie;
    } 
        return bestMovie;
});
bestMovie // [...] 'Amadues' 객체가 출력된다

이런 식으로 가장 평점이 높은 하나의 요소를 추출할 수 있다.
더하든 빼든 곱하든 비교하든 어떻게해서든 줄여 나가다가 값 하나만 남긴다.
어떻게 하든 우리에게 달렸다!

추가로 초기값도 지정할 수 있다.
.reduce(callback함수, 100) 뒤에 100과 같이 인수를 하나 더 쓰면
초기값을 100으로 시작해서 처리를 할 수 있다.


화살표 함수와 'this'

일반 함수와 화살표 함수에서 this는 다르게 동작한다.

const person = {
  firstName: 'Viggo',
  lastName: 'Mortensen',
  fullName: function () {
    return `${this.firstName} ${this.lastName}`
  },
  shoutName: function () {
    setTimeout(() => {
    	console.log(this);
      	console.log(this.fullName())
    }, 3000)
  }
}

위 의 fullName에서 화살표 함수를 사용하면
this가 window를 가리켜서 undefined를 반환한다.

화살표 함수 안에 있는 this 키워드는
함수가 만든 범위에 상속되는 this 키워드 값과 같다.

shoutName에서 화살표 함수를 사용하지 않았다.
그래서 아래에 있는 setTimeout에 화살표 함수를 사용해도
console.log에 찍히는 this가 person 객체를 가리킨다.

조금 헷갈리지만, 우선은 화살표 함수에서 this는 다르게 작동한다는 것에 집중하자..!

profile
두두

0개의 댓글