[JavaScript] map, filter 함수로 배열의 특정 요소 거르기(ft. 객체참조)

ryeoni·2022년 10월 18일

JavaScript

목록 보기
5/11

개요


map()filter()를 이용하여 원하는 조건의 배열만 반환하고
반환한 배열의 일부 속성값을 변경해보자!


특정 조건에 해당하는 배열만들기


const arr = [
  { n: 10, s: "강아지" },
  { n: 10, s: "고양이" },
  { n: 10, s: "사자" },
  { n: 20, s: "돌고래" },
  { n: 30, s: "다람쥐" },
];

n = 10 요소만 걸러서 새로운 배열만들기


map()


map() 을 돌리고 원하는 조건에 해당할 경우 push() 로 배열 끝에 항목을 추가한다.

let newArr = [];
arr.map(v => {
  if (v.n === 10) {
    newArr.push(v);
  }
});

/*
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 10, s: '사자'}
*/

중괄호를 지우고 if 조건문을 && 연산자로 고치면 아래와 같다

arr.map(v => v.n === 10 && newArr.push(v));

바로 newArr 에 대입할 경우

let newArr = arr.map(v => {
  if (v.n === 10) return v;
});

// [{…}, {…}, {…}, undefined, undefined]

조건에 해당되지 않으면 undefined 값이 반환된다.
undefined 를 제외한 새로운 배열을 만들려면 filter를 사용해야 한다.


filter()


filter() 메서드는 조건에 해당되는 요소를 모아 새로운 배열로 반환한다.
조건에 따라 true, false 를 반환하며 false 를 반환할 경우 버리므로
위의 경우는 filter가 적합하다.

let newArr = arr.filter(v => v.n === 10);

/*
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 10, s: '사자'}
*/

특정 요소의 속성값 변경하기



s = 사자일 경우 n = 40으로 변경하기


newArr.map(v => {
  if (v.s === "사자") v.n = 40;
});

newArr 배열은 무리없이 잘 변경되었지만...


/*
newArr
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 40, s: '사자'}
*/

원본 배열인 arr 배열도 같이 변경되었다!


/*
arr
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 40, s: '사자'}
3: {n: 20, s: '돌고래'}
4: {n: 30, s: '다람쥐'}
*/

원본 배열은 그대로 두고 newArr 배열만 수정하고 싶었기 때문에 배열의 복사본을 대입하였다


newArr.map((v, i) => {
  if (v.s === "사자") newArr[i] = { ...v, n: 40 };
});

해석하자면 조건에 해당되는 newArr 배열의 인덱스에 n은 40으로 변경하고 나머지 값은 그대로 복사한다. 객체를 직접 수정하는게 아니라 복사본을 대입하였기 때문에 원본 데이터에는 손상이 가지 않는다.


/*
newArr
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 40, s: '사자'}
*/
/*
arr
0: {n: 10, s: '강아지'}
1: {n: 10, s: '고양이'}
2: {n: 10, s: '사자'}
3: {n: 20, s: '돌고래'}
4: {n: 30, s: '다람쥐'}
*/

Object reference


newArr의 속성값을 변경했는데 arr의 값도 같이 변경된 이유는 참조관계가 이루어 졌기 때문이다.


let newArr = arr;
console.log(arr === newArr); // true

newArr 변수에 arr 배열의 값을 대입하면 참조 관계가 이루어지며 객체의 복사본 대신 동일한 객체에 링크되는 객체 참조를 보유하여 어느 하나의 객체 내 속성값을 변경하면 참조 관계에 있는 다른 객체의 속성 값도 변경된다.


참조관계로 이루어졌다고 해도 arr 배열은 변경할 수 없는 상수인 const로 선언됐는데 왜 객체의 속성이 변경됐을까?


객체를 참조로 저장하기 때문에 const 객체의 속성을 수정할 수 있다

const user = {
  name: "John"
};

user.name = "Pete"; // possible
// user = "Pete" // error

alert(user.name); // Pete

user=... 처럼 전체를 변경할 때는 오류가 발생하지만 객체의 속성은 자유롭게 변경할 수 있다.


요약

객체는 참조로 할당 및 복사된다. 즉, 변수는 객체 값 이 아니라 값에 대한 참조(메모리의 주소)를 저장한다. 따라서 이러한 변수를 복사하거나 함수 인수로 전달하면 개체 자체가 아니라 해당 참조가 복사된다.
복사된 참조를 통한 모든 작업(예: 속성 추가/제거)은 동일한 단일 개체에서 수행된다.
실제로 복사하기 위해 얕은 복사 또는 깊은 복사 를 이용하거나 lodash_.cloneDeep(value) 을 사용해야 한다.


객체 참조에 대한 내용은 아래 문서에 자세히 정리되어 있다.

Object references and copying


Reference


Array.prototype.map()
Array.prototype.filter()
Object reference
객체 간 참조 관계 및 해제 방법

profile
기록하는 습관 ✏️ 공유하고 싶은 정보들 🔎

1개의 댓글

comment-user-thumbnail
2022년 11월 7일

👍👍

답글 달기