프로그래밍 언어/JavaScript

[JS] 얕은 비교, 깊은 비교 / 얕은 복사, 깊은 복사

tteokbokki-master 2024. 4. 26. 16:51

얕은 비교

숫자, 문자열 등 원시 자료형은 값을 비교한다.

배열, 객체 등 참조 자료형은 값 혹은 속성을 비교하지 않고, 참조되는 위치를 비교한다.

 

const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };

console.log(obj1 === obj2); // false

 

값 대신 참조 위치를 비교하기 때문에 false가 나온다.

 

 

 

 

 

깊은 비교

 

얕은 비교와 달리 깊은 비교는 객체의 경우에도 값으로 비교한다.

const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };

console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // true

JSON.stringify()를 사용한다.

 

 

 

 

 

얕은 복사

객체의 최상위 프로퍼티만 복사하는 방법으로, 중첩된 객체는 참조값으로 유지된다. 

// 스프레드 연산자를 통한 복사 

const aArray = [1,2,3];
const bArray = [...aArray, 4];

console.log('aArray', aArray); // aArray [ 1, 2, 3 ]
console.log('bArray', bArray); // bArray [ 1, 2, 3, 4 ]
console.log('aArray === bArray', aArray === bArray); // aArray === bArray false


// Object.assign()을 통한 복사

const cArray = Object.assign([],bArray);
console.log(‘cArray’, cArray); // cArray [ 1, 2, 3, 4 ]
console.log(‘bArray === cArray’, bArray === cArray); // bArray === cArray false

 

 

 

왜 얕은 복사인가?

다음과 같이 aArray 배열을 복사하고 10을 추가한 bArray가 있다고 하자. 각각 [ 1, 2, 3, [ 4, 5, 6 ] ] [ 1, 2, 3, [ 4, 5, 6 ], 10 ]  값이 출력되는 것을 확인할 있다.

 

 

 

이때 bArray의 중첩된 배열의 값에 7을 추가하고 aArray와 bArray를 다시 출력해 본다. 오잉? 분명히 bArray의 값만 변경했음에도 불구하고 aArray의 값도 변경되었다. 왜 그럴까?

 

 

 

중첩된 객체는 원래의 참조값을 유지한다. 위의 코드를 비교해 보면 aArray와 bArray를 비교했을 때는 false가 나오는 반면, 중첩된 부분인 aArray[3]과 bArray[3]을 비교했을 때는 true가 나오는 것을 확인할 수 있다.

 

그래서 값을 변경했을 때 같이 변경되는 것이고, 이렇게 깊은 부분까지는 복사가 안되니까 얕은 복사라고 하는 것이다.

 

 

 

 

 

얕은 동결

const aObject = {
  "a" : "a",
  "b" : "b",
  "cObject" : {"a" : 1, "b" : 2}
}
Object.freeze(aObject);

aObject.a = 'c';
console.log(aObject.a); // a

Object.freeze()로 동결된 객체는 더 이상 변경될 수 없다. 그래서 a를 ‘c’로 변경했음에도 변경되지 않고 그대로 a가 출력된다.

 

 

 

const aObject = {
  "a" : "a",
  "b" : "b",
  "cObject" : {"a" : 1, "b" : 2}
}
Object.freeze(aObject);

aObject.cObject.a = 10;
console.log(aObject.cObject.a); // 10

하지만 얕은 동결인 만큼 객체 안에는 동결시키지 못한다. 동결됐음에도 cObject의 a값이 10으로 변경된 것을 확인할 수 있다.

 

 

 

 

 

깊은 복사

얕은 복사와 다르게 중첩된 객체까지 모두 복사하여 완전히 독립적인 복사본을 만드는 것이다. 

const aObject = {
  "a" : "a",
  "b" : "b",
  "cObject" : {"a" : 1, "b" : 2}
}

const newAObject = JSON.parse(JSON.stringify(aObject));
console.log('aObject', aObject); // aObject { a: 'a', b: 'b', cObject: { a: 1, b: 2 } }
console.log('newAObject', newAObject); // newAObject { a: 'a', b: 'b', cObject: { a: 1, b: 2 } }

aObject.cObject.a = 3;
console.log('aObject', aObject); // aObject { a: 'a', b: 'b', cObject: { a: 3, b: 2 } }
console.log('newAObject', newAObject); // newAObject { a: 'a', b: 'b', cObject: { a: 1, b: 2 } }

얕은 복사와 다르게, 배열이나 객체로 중첩된 부분도 처리를 해준다. 그래서 중첩된 부분의 값을 변경해도 같이 변경되지 않는 것을 확인할 수 있다.