1. for문과 배열(array) 함께 사용하기
잠시 헷갈렸던점 : anmes.length를 하면 안에 3개가 있으니까 3개로 찍히고,
배열에서 꺼내올때는 0부터 꺼내와야하므로 3 멍뭉이 가 아닌 2 멍뭉이 이다.
배열 내장함수 시작
내장 함수를 사용하게 될때, 하나하나 외운다기보다는 하나하나의 함수들이 어떤 용도로 사용되는지
잘 이해하고, 나중에 써야될때 자동완성이되고, 주석(설명) 이 나오니까 그것들만 보고도 내가
사용할 수 있을정도로만 공부해도 충분하다!
2. forEach
각 원소들에 대하여 반복적으로 계속 호출하여 출력 할 수있다.
const superheroes = ["아이언맨", "캡틴아메리카", "토르", "탁터 스트레인지"];
//방법 1.
// function print(hero) {
// console.log(hero);
// }
// superheroes.forEach(print);
//방법 2.
// superheroes.forEach(function (hero) {
// console.log(hero);
// });
//방법 3.
superheroes.forEach((hero) => {
console.log(hero);
});
//아이언맨
//캡틴아메리카
//토르
//탁터 스트레인지
//토니 스타크
방법1 -> 방법2 -> 최종 방법 3으로 코드가 점차 줄어든것을 확인 할 수 있다.
따라서 배열 안에있는 원소들을 가지고 어떤 작업을 일괄적으로 하고싶다면 forEach를 사용하자.
3. map
모든 원소를 다른형태로 변환하고 싶을때 사용한다.
const array = [1, 2, 3, 4, 5, 6, 7, 8];
//만약 위의 배열안에있는 모든 숫자를 제곱해서 새로운 배열을 만들고싶다면 ?
// const squared = [];
//방법 1.
// for (let i = 0; i < array.length; i++) {
// squared.push(array[i] * array[i]);
// }
//방법 2.
// array.forEach((num) => {
// squared.push(num * num);
// });
//방법 3.
const square = (n) => n * n;
const squared = array.map(square);
//방법 4. --위의 코드에서 함수 자체를 map안에 넣은것이다.
const squared = array.map((n) => n * n);
console.log(squared);
map사용법은 방법3,4 번은 번을 참고하자.
정리해보자면 map은 const array = [1, 2, 3, 4, 5, 6, 7, 8]; 와 같이 배열이 있을때,
배열 안에들어있는 1, 2, 3, 4, 5, 6, 7, 8 원소들을 가지고 전체적으로 변환을 해주고싶을때 사용하는 내장함수이다.
이런것을 활용하면 아래와 같은것도 할 수 있다.
const items = [
{
id: 1,
text: "hello",
},
{
id: 2,
text: "bye",
},
];
객체로 이루어진 배열 즉, 객체의 배열들을 text만 이루어진 문자열 배열로 바꾸고싶다면 어떻게 할 수 있을까?
const texts = items.map((item) => item.text);
console.log(texts);
라고해주면, [ 'hello', 'bye' ] 라고 출력결과가 나오는 것을 확인할 수 있다.
⭐이번에는 배열에서 원하는 항목이 어디에있는지 알려주는함수들에 대해 알아보자
4. indexOf
특정 항목이 배열에서 몇번째 원소인지 알고싶다면 배열.indexOf 즉, indexOf라는 배열 내장함수를 사용하면된다.
const superheroes = ["아이언맨", "캡틴 아메리카", "토르", "탁터 스트레인지"];
const index = superheroes.indexOf("토르");
console.log(index); // 2
또 이와 비슷한 함수로 findIndex함수가있다.
만약, 배열안에 있는 값이 문자열이나 숫자 혹은 boolean이면 찾고자하는 항목이 몇번째 원소인지를 알고싶을때 충분히 indexOf로도 할 수가있다.
그런데 만약 배열안에 들어있는 값들이 객체이거나, 특정값이랑 일치하는것을 찾는게 아니라 어떠한 조건으로 찾는다면 indexOf로는 찾을 수가 없다.
5. findIndex
const todos = [
{
id: 1,
text: "자바스크립트 입문",
done: true, //했는지안했는지
},
{
id: 2,
text: "함수 배우기",
done: true, //했는지안했는지
},
{
id: 3,
text: "객체와 배열 배우기",
done: true, //했는지안했는지
},
{
id: 4,
text: "배열 내장함수 배우기",
done: false, //했는지안했는지
},
];
만약 위의 코드에서 id가 3인것을 찾고싶으면 어떻게 해야될까?
const index = todos.indexOf(3);
console.log(index);
위의 결과같은 -1 이 나온다.
이 -1의 의미는 일치하는게 없다 라는 의미이다.
그래서 만약 위의 superheroes 배열에서도 내가 토르라는 원소를 찾고싶은데, 이게 id값이 3일경우 만약 3을 찾았는데 없다면 -1이 나왔을 것이다.
따라서 indexOf를 사용했을때 -1이 나왔다는 것은 없다는 소리이다.
그럼이제 다시 돌아와서 todos 배열에서 내가 id가 3인것을 찾고싶다라고했을때 findIndex를 사용해야된다.
findIndex 파라미터에 넣어야되는것은 함수이다.
특정조건을 확인해서,그 조건이 일치한다면 일치하는 원소가 몇번째인지 알려준다.
const index = todos.findIndex((todo) => todo.id === 3);
console.log(index); //2
따라서 이렇게 작성을 해주면, 출력결과로 2가 나온다! (꺼내올때는 0부터 시작하니까!)
그래서 만약 배열안에있는 값들이 객체인거나 아니면 특정 조건을 확인해야되는경우!
즉, 지금의 예제코드는 id가 3인것만찾는 비교적 단순한 조건이지만,
만약 숫자배열이면서 나누기2했을때 값이 4인것만 찾는 이런 특정 조건에 대해서 몇 번째인지 확인해야되는 경우
findIndex를 사용하면 된다.
6. find
findIndex 조금 비슷하며, 어떻게 다른지 한 번 살펴보자.
findIndex는 몇 번째인 알려주는지 확인해야되는 경우 사용했다면, find를 하게되면 그 객체자체 혹은 객체가 아닌 원소 (숫자 혹은 다른 값들) 일 수도있는데, find해서 그 값을 반환한다.
따라서
const todo = todos.find((todo) => todo.id === 3);
console.log(todo); //{ id: 3, text: '객체와 배열 배우기', done: true }
그냥 findIndex에서 find로 해주면 반환하는것은
그냥 id가 3인, todo 객체인 { id: 3, text: '객체와 배열 배우기', done: true } 가 출력된다
find도 특정 조건으로찾으며,
예를들어 done === false 인것을 찾게될경우는? 아래와 같이 작성된다.
const todo = todos.find((todo) => todo.done === false);
console.log(todo); //{ id: 4, text: '배열 내장함수 배우기', done: false }
그리고 이제, 총 정리를 해보자면, indexOf , findIndex , find같은경우는
이 세가지 함수는
- 어떤 값을 찾고싶을때 그게 어디에 있는지 찾거나 혹은 그 값 자체를 사용하고 싶을때 사용하면 된다.
- 가장 첫번째로 찾은 항목을 알려준다.
indexOf : 특정값이랑 일치하는것을 찾을때 사용
findIndex : findIndex내부에 함수를 넣어줘서 특정 값을 조건으로 찾아서 내가 원하는 값이 몇 번째인지 알 수 있다.
find : 찾은 값 자체를 반환하는것이다.
7. filter
특정 조건에 만족하는 원소들을 찾아서 그 원소들을 가지고 기존의 배열은 건들이지 않고, 새로운 배열을 만드는 것이다.
그래서 만약 todos배열에서 done값이 true인 것들만 따로 필터링 하겠다! 라고하면 filter함수를 사용하면된다.
//방법1.
const tasksNotDone = todos.filter((todo) => todo.done === true);
//방법2. -- 더 간략하게 작성
const tasksNotDone = todos.filter((todo) => todo.done);
console.log(tasksNotDone);
//[
// { id: 1, text: '자바스크립트 입문', done: true },
// { id: 2, text: '함수 배우기', done: true },
// { id: 3, text: '객체와 배열 배우기', done: true }
//]
또 반대로 done값이 false인 것만 찾게되면 아래와 같이 작성이 가능하다.
방법1.
const tasksNotDone = todos.filter((todo) => todo.done === false);
//방법2. -- 더 간략하게 작성
const tasksNotDone = todos.filter((todo) => !todo.done);
//[ { id: 4, text: '배열 내장함수 배우기', done: false } ]
정리해보자면, filter은 특정배열에서 특정 조건을 만족하는 그런 원소들만 추출해서 새로운 배열을 만들때 사용하면된다.
8. splice
splice 특정항목을 제거할때 사용한다 그리고 제거를 하는 과정에서 해당 원소가 몇 번째인지 명시를 해줘야된다.
const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
console.log(index); //2
만약 여기서 우리가 index가 2인것을 지우고싶다면?
const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
// console.log(index); //2
numbers.splice(index, 1); //index부터 지정한 몇개를 지워주겠다!
console.log(numbers);
//출력결과:
//[ 10, 20, 40 ]
그리고 나아가 numbers.splice의 결과값은 제거한 배열들을 의미하게되는데, 따라서
결과값을 확인하기위해 아래의 코드를 추가해보자.
const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
const spliced = numbers.splice(index, 2);
console.log(spliced); //[ 30, 40 ]
console.log(numbers); //[ 10, 20 ]
따라서 2번째 줄 index는 2 이이고, 3번째줄 splice(2부터 2개를 지우겠다) 라고해서 spliced로 들어오고
cpliced 는 30,40 이 지워졌다는것이보이게되고,
numbers는 배열안에 남은 원소들이 보이게되는것이다.
9. slice
splice와 비슷하게 배열에서 뭔가 잘라내는 것을 의미하는데 하지만 역할도 다르고 사용법도 다르다.
slice는 배열을 잘라낼때 사용하는데, splice와의 차이점은 기존의 배열을 건드리지 않는다는 것이며, 그리고 파라미터에 넣게되는 값 또한 조금 다르다.
const numbers = [10, 20, 30, 40];
const sliced = numbers.slice(0, 2); //0부터 시작해서 2전까지
console.log(sliced); //[ 10, 20 ]
console.log(numbers); //[ 10, 20, 30, 40 ]
이와같이 출력되는 결과를 확인할 수 있으며, 다시 한 번 강조하자만 slice는 기존의 배열을 건드리지 않는다!
반면 splice는 기존의 배열을 수정해버린다. -> 이것이 두개의 가장 큰 차이점이다!
10. shift
첫번째 원소를 배열에서 추출해준다.
그리고 shift는 기존의 배열을 수정하게된다.
const numbers = [10, 20, 30, 40];
const value = numbers.shift();
console.log(value); //10
console.log(numbers); //[ 20, 30, 40 ]
그럼 numbers.shift( )를 여러번하게되면 어떻게될까?
const numbers = [10, 20, 30, 40];
const value = numbers.shift();
numbers.shift();
numbers.shift();
numbers.shift();
console.log(value); //10
console.log(numbers); //[]
아무것도 없을때까지 다 빠지게되며, 아무것도 없을때는 그냥 비워져 있게된다.
따라서 shift는 맨 앞에있는 원소 하나씩 밖으로 꺼내는것을 의미하며, 바닥 날때까지 계속한다.
11. pop
shift는 왼쪽에서 빼내는것이라면, pop은 오른쪽에서부터 빼낸다.
const numbers = [10, 20, 30, 40];
const value = numbers.pop();
console.log(value); //40
console.log(numbers); //[ 10, 20, 30 ]
또 numbers.pop( )을 여러번 하게되면 똑같이 아무것도 없게되면 딱히 error는 나지않고, 그냥 비어있는 배열이된다.
const numbers = [10, 20, 30, 40];
const value = numbers.pop();
numbers.pop();
numbers.pop();
numbers.pop();
console.log(value); //40
console.log(numbers); //[]
12. unshift
const numbers = [10, 20, 30, 40];
numbers.unshift(5);
console.log(numbers); //numbers 배열의 맨 앞부분에 5를 추가하는것이다.
//출력결과:
//[ 5, 10, 20, 30, 40 ]
그럼 우리가 예전에 배웠던 push함수도 있는데, 굳이 짝을 지운다면
push - pop 이랑 짝이고, shift - unshif와 짝이다.
push - pop :
const numbers = [10, 20, 30, 40];
numbers.push(50);
console.log(numbers); //[ 10, 20, 30, 40, 50 ]
const value = numbers.pop();
console.log(value); //50 뺀다.
console.log(numbers); //[ 10, 20, 30, 40 ]
shift - unshif :
const numbers = [10, 20, 30, 40];
numbers.unshift(0);
console.log(numbers); //[ 0, 10, 20, 30, 40 ]
const value = numbers.shift();
console.log(numbers); //[ 10, 20, 30, 40 ]
그래서 정리하자면, push와 unshift가 배열안에서 넣는것이고, shift랑 pop이 배열에서 밖으로 빼는것이다.
그리고 이 4가지 함수는 numbers배열 자체를 바꿔버린다는것을 알고있자!
13. concat
여러개의 배열을 하나의 배열로 합쳐주는 작업을 해준다.
기존의 배열을 건드리지않는다. ->대신 그 결과를 새로운배열로 만들면서 concated에다가 담는다.
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const concated = arr1.concat(arr2);
console.log(arr1);
console.log(arr2);
console.log(concated);
//출력결과:
//[ 1, 2, 3 ]
//[ 4, 5, 6 ]
//[ 1, 2, 3, 4, 5, 6 ]
es6연산자 중에서 스프레드연산자가있다.
따라서 const concated = arr1. concat(arr2); 대신에 const concated = [...arr1, ...arr2];
로 대신해서 사용할 수 있다. 이것에 대해서는 다음 포스팅에서 다루겠다.
그리고 의미가 비슷해서 쫌 헷갈릴 수 있는 내장함수join을 알아보자.
14. join
배열안에 있는 값들을 문자열 형태로 합쳐줄때 사용한다.
const array = [1, 2, 3, 4, 5];
console.log(array.join());
//출력결과:
//1,2,3,4,5
//파라미터로 separator를 넣어줄수도있다. 어떻게 구분할 것인가?를 넣어줄 수 있다.
console.log(array.join(" "));
//출력결과:
//1 2 3 4 5
console.log(array.join(", "));
//출력결과:
//1, 2, 3, 4, 5
즉 array있는 배열을 쉼표 사이사이에 넣어서 하나의 문자열로 만들어주었다.
15. reduce
reduce함수는 잘 사용하면 진짜 유용한 함수이다.
주로, 배열이 주어졌을때 배열에 있는 모든 값들을 사용해서 어떤값들을 연산해야될때사용한다.
즉, 각원소들에 대하여 loop를 돌려서 누적된 값을 연산하는 함수를 만든다.
예를들어서 다음의 코드를 살펴보자.
우리가 지금까지 배운 함수를 사용해서 다음의 numbers배열에 있는 값들을 더하려고하면
const numbers = [1, 2, 3, 4, 5];
let sum = 0;
numbers.forEach((n) => {
sum += n;
});
console.log(sum); //15
이와같이 할 수 있을텐데, reduce를 사용하면 한줄로 구현이 가능해진다.
첫번째 파라미터로는 어떤 누적된 값을 계산할껀데 그 값을 계산하는 함수를 넣을꺼고,
이 함수는 2가지(accumulatro , current) 의 파라미터를 받아오게된다.
그리고 결과 값으로는 accumulatro , current값을 어떻게 연산할지를 설정한다.
첫번째 파라미터 accumulatro에는 +를 해주고, 두번째 파라미터 함수 다음에 넣어줘야되는 값은 accumulatro의 기본값인 0을 넣어준다.
그래서 우선 코드를 보면 다음과 같다.
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulation, current) => accumulation + current, 0);
console.log(sum); //15
쟈! 다시 정리해보자면 이렇다.
0은 초기 accumulator(누적된 값을 의미한다)가 된다.
초기값 0이 (accumulator, current)의 accumulator가된다.
다음 current는 각 원소들을 가르키는데, 따라서 처음에는 1이 들어갈텐데
( 0, 1 ) => 0+1, 1 //초기값 0 accumulator가 1이되었다.
다시 한번 반복하자면 누적된 1값이 다시..
( 1, 2 ) => 1+2, 3 //3
.
.
이런식으로 반복이되면서 결과값으로 15가 출력되는것이다.
그리고 reduce를 사용해서 배열의 평균을 구할수도있다.
(accumulator, current) 말고도 추가적으로 index, array까지 받아올 수 있다.
const sum = numbers.reduce(
(accumulation, current, index, array) => accumulation + current, 0);
index는 reduce에서 (accumulator, current) 함수가 numbers에 있는 각 원소에 대해서 실행이 될텐데,
이때 index는 각 원소가 몇 번째 item인지 알려준다. 따라서 0,1,2,3,4 까지 실행이되고,
여기서의 array는 우리가 함수를 실행하고있는 자기 자신을 의미한다.
다음의 코드를 보자.
const numbers = [1, 2, 3, 4, 5];
const avg = numbers.reduce((accumulation, current, index, array) => {
if (index === array.length - 1) {
//현재 처리하고있는 원소가 맨 마지막꺼라면 5-1=
return (accumulation + current) / array.length;
}
return accumulation + current;
}, 0);
console.log(avg); //3
작동방식이 헷갈려서 아래처럼 그려보았는데, 뭔가 지저분한 것 같지만...
그래도 9번째 줄부터 초기값 0 으로 세팅된것이 3번째 줄로 세팅되는 것부터 시작하면 어렵지않다.
reduce함수는 기존에 배웠던 함수들보다는 조금 어렵고, 복잡하지만
이거를 완벽히 작동방식을 이해하고 난다면 완전완전 다양한 곳에서 써먹을수있다.
또한 reduce함수는 꼭 숫자들만이 아니라 문자들 또한 사용할 수 있다.
다른예시로, 각알파벳들이 배열안에 몇개씩 있는지 세서, 객체에 결과를 넣어줘보겠다!
const alphabets = ["a", "a", "a", "b", "c", "c", "d", "e"];
const counts = alphabets.reduce((acc, current) => {
//만약에 acc안에있는 current가 존재하는지 확인한다.
//이 말이 무슨말이냐하면 acc[current]-> acc['a'] ->acc.a
if (acc[current]) {
acc[current] += 1;
} else {
acc[current] = 1;
}
return acc;
}, {}); //숫자 0이 아닌, 객체{} 를 넣어주었다.
console.log(counts);
//출력결과 :
//{ a: 3, b: 1, c: 2, d: 1, e: 1 }
따라서 이 코드의 작동방식은 이렇다.
처음에는 2번째줄의 acc가 비어있는 객체(11번째줄) { } 이니까, acc는 { } 이고, current는 'a' 이다.
그리고, 5번째줄에서 11번째줄에있는 비어있는 객체에 'a' 가 있는지 확인한다.
그래서 'a'가 없으니까 객체안에 a값을 1이라고 먼저 만들것이다.
그리고 그 다음 loop를 돈다.
그러면 그 다음 loop에서는 acc안에 {a:1} 이라고 들어있을 것이다.
acc안에 a가 존재하니까 거기에 1을 더해서 2가되고, 또 3이된다.
그리고 'b'가 왔을때는 없으니까 1이된다.
이런식으로
c, d, e 또한 처리되어 결과적으로 { a: 3, b: 1, c: 2, d: 1, e: 1 } 되는것이다.
❗❗기존의 배열을 건드리지(수정하지) 않는 함수정리 :
slice, concat
❗❗다시 한 번 중요한 함수 :
reduce
참고자료 :
최근댓글