배열(Array)의 함수들 정리해보기

요오드용액·2022년 2월 14일

프론트엔드

목록 보기
4/4

오늘은... 자꾸만 헷갈려서 맨날 MDN문서를 뒤져보고 다니는 Array에 사용되는 함수들을 몇 개 다시 연습해보기로
헷갈릴 때 찾아볼 용도로 적는 거라 진짜 대~~~충 적었음

array의 설명 출처는 mdn을 기반으로 작성합니다(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array)

배열(Array)의 함수들

내가 가끔 까먹고 헷갈려하는 것들 몇 개 추려보자면

concat()
every()
filter()
map()
reduce()
slice() vs splice()
sort()

vs로 한건 결이 비슷한 함수들이라 데려와봤다.

concat()

기존 배열을 합쳐 새 배열을 만드는 함수
기존 배열은 변경되지 않으며, 새로운 배열을 반환한다

//두 개의 배열
let a = [1,2,3,4,5];
let b = [6,7,8];

let c = a.concat(b);

console.log(a);	//[1,2,3,4,5]	변경x
console.log(b);	//[6,7,8]		변경x
console.log(c);	//[1,2,3,4,5,6,7,8]

배열을 합쳐준다고 생각하자!
대신 기존 배열이 변경되지 않고 새 배열이 반환되니까, 필요하다면 다른 변수에 이 반환된 배열을 담아서 쓸 수 있다.

concat()은 두 배열만 합칠 수 있는 게 아니다. 두 개 이상도 가능!

let a = [1,2,3,4,5];
let b = [6,7,8];
let c = ['a','b','c'];

let d = a.concat(b,c);

console.log(d)	//[1,2,3,4,5,6,7,8,'a','b','c']

만약 concat()에 인자를 넣지 않는다면?
기존 배열을 얕은 복사해서 반환한다.
즉 복사된 배열 내 값을 변경해도 기존 배열은 멀쩡할 거라는 것

let a =[1,2,3];
let b = a.concat();		//b = [1,2,3]

b.push(4);				//b = [1,2,3,4]
						//a = [1,2,3]	변경x

얕은 복사가 되었기 때문에,
b에 어떤 값을 넣어도, 혹은 값을 변경해도 a는 멀쩡하다는 것이 보인다.

every()

배열 내 모든 요소가 주어진 함수를 모두 통과하는지 알아낸다
반환값은 boolean!
every()의 괄호 안에는 함수가 들어간다

every니까 말 그대로 배열 내 값들을 "모두" 확인해야지

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

a.every(function(element,index,array){
	return element > 0;		//true 반환
})

배열 내 모든 값이 0보다 크기 때문에 true를 반환합니다!

만약 모든 값들을 충족시키지 못하는 조건(ex: 0보다 작다)을 쓰면 false값이 뜹니다.

(저렇게 함수로 쓸 거라면 return을 꼬옥...써주자 까먹고 그냥 쓰면 뭐든 false값이 뜬다.)


위 처럼 함수를 써도 되고, 화살표 함수로 줄이는 것도 가능

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

a.every( (element)=>{element>0} )

짧은 코드라서 더욱 간단해졌다.

filter()

주어진 함수를 통과한 값들만 모아서 새 배열을 반환한다
반환값이 새로운 배열
주어진 함수를 요소마다 체크한다는 점에선 every()와 비슷하니 잘 알아두기

필터 함수는 새로운 배열 반환
필터 함수는 새로운 배열 반환!!

간단한 예시로 보면

let a = [1,2,3,4,5]

let b = a.filter(function(element){
	return element > 3;
})

console.log(b)	//[4,5]

아! 맞아

filter의 콜백함수 첫 번째 인자는 배열의 요소, 두 번째 인자는 인덱스, 세 번재 인자는 호출된 배열 자체가 된다
(보통 다른 콜백 함수들도 이렇게 인자를 가지고 있더라)

첫 번째 인자인 element들이 3을 넘는다면 그 녀석들만 뽑아서 배열이 생성되고, b에 담겨지는 것!

map()

배열 내 요소들이 주어진 함수를 거친 결과 나온 값들을 모아서 새로운 배열로 반환한다.
filter()와 비슷하다는 점 주의!
둘 다새 배열을 반환한다는 점은 비슷하지만, filter()는 통과되어 걸러진 녀석들을 요소로 잡고
map()은 결과 값들이 요소로 잡힌다는 점

filter는 걸러진(filtered) 녀석들이 등장하는 거고,
map은 모든 요소들이 재탄생(?)되어 등장한다

명심하자
filter는 걸러진 놈들!
map은 재탄생하는 놈들!

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

let b = a.map(function(element){
	return element * 2;
})

console.log(b);		//[2,4,6,8,10]

주어진 함수는 각 요소들을 2배 해주는 함수.
배열의 각 요소들이 2배 당하고 나면 각각 2,4,6,8,10 이 된다.
새 배열이 반환된다고 했으니, 이 녀석들을 배열에 넣어주면 [2,4,6,8,10]이 되는 것이다.

reduce

주어진 함수(reducer라고 한다)에 배열의 각 요소들이 들어가 함수를 실행하고, 하나의 값으로 반환된다.
누적된 계산의 값이 최종 반환되는 것!

리듀서 함수에는 네 개의 인자가 들어갈 수 있다

[배열].reduce(function(acc,cur,idx,src){
// ...
})

acc(누산기): 함수를 거쳐서 나온 반환 값
cur(현재 값): 현재 요소 값
idx(현재 인덱스): 현재 요소를 가리키는 인덱스
src(원본 배열)

리듀서 함수는 배열의 각 요소마다 함수를 실행한다(forEach처럼).
한 번 함수를 실행할 때마다 나오는 결과값을 acc에 저장하고, 다음 요소가 있다면 다시 함수를 돌린다.
글로 쓰니까 말이 이상하네

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

a.reduce(function(acc,cur,idx,src){
    return acc + cur;	// 15
})

처음 시작할 때 acc에는 배열의 첫 요소가 들어간다. 위 코드를 본다면 1이 들어간다.
그렇다면 cur에는 다음 요소인 2가 들어가고.

1+2를 리턴하면 3이 되니까,
다음 acc에는 누적값인 3이 들어가고,
cur은 3이 들어가는 것.

💡 짚고 넘어가야 할 점

reduce()함수의 매개변수를 더 자세히 보자

기본 형태는
arr.reduce(callback [, initialValue] )

콜백함수 옆에 있는 매개변수가 있냐 없냐에 따라 결과값이 달라진다.

initialValue는 콜백함수를 처음 호출할 때, 첫번째 인수인 acc에 들어갈 초기값을 정해준다!

위 코드에서는 initialValue값을 정해주지 않았기 때문에 초기값으로 배열의 첫 번째 요소가 acc에 들어갔지만,
값을 세팅하면 initialValue가 acc로 들어갈 것이다.


짧은 예시만 하나 쓰고 다음으로 넘어가본다.
위랑 같은 코드지만 initialValue값만 지정해준 코드

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

a.reduce(function(acc,cur,idx,src){
    return acc + cur;	// 20
},5)

//초기값에 5가 들어갔으므로
// 5+1 = 6
// 6+2 = 8
// 8+3 = 11
// 11+4 = 15
// 15+5 = 20 이런순서로 진행된다

slice() vs splice()

개념은 알면서도 사소한 차이 때문에 꼭 검색했다가 적용하는 이 두 함수...

  • slice()는 원본 배열은 변하지 않은 채, 새로운 복사본 배열을 반환한다. 시작점 인덱스부터, 끝나는 인덱스 전까지 배열을 복사한다.
  • splice()는 기존 배열의 요소를 삭제, 혹은 추가한다. 원본 배열이 바뀐다는 점.

slice()

slice()함수의 형태는

arr.slice([begin[,end]])
  • begin은 시작 인덱스.
  • end는 종료 인덱스다.

begin을 포함한 값부터 시작해서 end전(!!)까지 배열을 복사한다.
명심하자. end인덱스 전까지 복사다.

begin 값과 end값은 둘 다 생략이 가능하다. 둘 다 생략될 경우 기존 배열을 그대로 복사해서 새 배열을 뱉는다. 게다가 얕은 복사가 되기 때문에 원본 배열이 변경될 일을 걱정하지 말자.

간단한 예시 또 가져오기

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

let b = a.slice(1,4);
console.log(b);		//[2,3,4]

첫 인덱스가 1이니 배열의 요소는 2부터 시작.
두번째 인덱스가 4이기 때문에 그 전!!인덱스의 값인 4까지가 복사되는 것이다.

splice()

splice()함수의 형태는

arr.splice(start[,deleteCnt[,item1[,item2[, ...]]]])

기니까 복잡해보이네...

  • start는 시작 인덱스
  • deleteCnt는 배열에서 제거될 요소의 갯수다. 0이 들어간다면 삭제되는 값이 없다. 만약 start값은 넣고 deleteCnt는 안 넣는다면? 시작 인덱스의 요소부터 끝까지 삭제되어 버린다.
  • item1, item2들의 경우 추가될 요소다! 없으면 그냥 이 함수는 제거작업만 진행한다.


    간단한 예시
let arr1 = ['a','b','c','d','e'];

arr1.splice(1,3);
console.log(arr1);		//['a','e']

//---------------------------------//

let arr2 = ['hi','name','KIM'];

arr2.splice(1,0,'my');
console.log(arr2);		//['hi','my','name','KIM']

  • 배열 arr1의 경우
    시작인덱스 1부터 시작하고 잘라낼 갯수는 3개다. 그렇다면 arr1[1]인 'b'부터 시작해서 3개를 잘라내므로, 'a'와 'e'만이 배열에 남게된다.

  • 배열 arr2의 경우
    시작인덱스 1부터 0개의 요소를 잘라낸다. 즉 잘라내는 값은 없다. 대신 뒤에 추가할 요소로 'my'를 넣어줬다.
    즉 인덱스1 위치에 'my'라는 요소를 추가하겠다는 뜻이 되므로, 배열은 ['hi','my','name','KIM']으로 바뀐다.

sort()

배열을 정렬한 후, 정렬된 배열을 반환. 복사본이 생기는 것이 아닌 원본 배열의 정렬이다.

일단 그냥 사용해본다면

let num = [1,2,1000,5,90];

num.sort();
console.log(num);	//[1,1000,2,5,90];

보통의 상식으로는 저딴 순서가 아니다. 함수를 사용하면 유니코드 순서에 따라 정렬되기 때문에(문자열로 변환), 2보다 1000이 앞서게 된다.

이런 정렬을 원하지 않는다면? 비교해주는 함수를 sort()안에 넣어줘야 한다.

let num = [1,2,1000,5,90];

num.sort(function(a,b){
	if(a>b) 		return 1;
    else if(a<b) 	return -1;
    else 			return 0;
});

a,b는 비교되는 요소.
a가 더 크다면, a가 b보다 큰 인덱스가 된다.
a가 더 작다면, a는 b보다 작은 인덱스가 된다.
a와 b가 동일하다면 서로 변경되지 않는다.

위를 더 간단하게 축약해서

num.sort(function(a,b){ 
	return a-b;
})

이렇게도 바꿀 수 있다. (a-b값을 0과 비교해서 어떤지에 따라 정렬되는 듯)


진짜 단순하게 정리한거지만, 그래도 나름 복기는 되는 것 같다.

profile
개발 공부하자..

0개의 댓글