map()과filter()를 이용하여 원하는 조건의 배열만 반환하고
반환한 배열의 일부 속성값을 변경해보자!
const arr = [
{ n: 10, s: "강아지" },
{ n: 10, s: "고양이" },
{ n: 10, s: "사자" },
{ n: 20, s: "돌고래" },
{ n: 30, s: "다람쥐" },
];
n = 10 요소만 걸러서 새로운 배열만들기
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()메서드는 조건에 해당되는 요소를 모아 새로운 배열로 반환한다.
조건에 따라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: '다람쥐'}
*/
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) 을 사용해야 한다.
객체 참조에 대한 내용은 아래 문서에 자세히 정리되어 있다.
Array.prototype.map()
Array.prototype.filter()
Object reference
객체 간 참조 관계 및 해제 방법
👍👍