객체의 복사

·2023년 1월 20일
0

역시나 모던 자바스크립트 참고 자료


객체의 복사

객체와 원시 타입의 근본적인 차이 중 하나는

  • 객체는 ‘참조에 의해(by reference)’ 저장되고 복사됩니다.
  • 원시값(문자열, 숫자, 불린 값)은 ‘값 그대로’ 저장·할당되고 복사됩니다.

원시값의 동작 방식:

<script>
let message = "Hello!";
let phrase = message;
</script>
  • 실행하면 두 개의 독립된 변수에 각각 문자열 "Hello!"가 저장됩니다.
  • 값을 똑 떼서 복사했을 뿐, phrase에 새로운 값을 할당해도 message의 값이 변하지 않습니다.

객체의 동작 방식:

<script>
let user = {
  name: "John"
};
</script>
  • 변수에 객체가 그대로 저장되는 것이 아니라, 객체가 저장되어있는 '메모리 주소’인 객체에 대한 '참조 값’이 저장됩니다.
    이게 무슨 소리냐면

  • 객체는 메모리 내 🛰️어딘가에 저장되고, 변수 user엔 객체를 '참조’할 수 있는 값이 저장됩니다.

  • 따라서 객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체 자체가 복사되지 않습니다.

예시:

<script>
let user = { name: "John" };

let admin = user; // 참조값을 복사함
</script>
  • 변수는 두 개이지만 각 변수엔 동일 객체에 대한 참조 값이 저장됩니다.

객체는 같은 값을 참조 해옵니다:

<script>
let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // 'admin' 참조 값에 의해 변경됨

alert(user.name); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함
</script>

객체 = 🗃️

변수 = 🔑

서랍장은 하나, 서랍장을 열 수 있는 열쇠는 두 개인데, 그중 하나(admin)를 사용해 서랍장을 열어 정돈한 후, 또 다른 열쇠로 서랍장을 열면 정돈된 내용을 볼 수 있습니다.


참조에 의한 비교

  • 객체 비교 시 동등 연산자 ==와 일치 연산자 ===는 동일하게 동작합니다.
  • 비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참을 반환하죠.
<script>
let a = {};
let b = a; // 참조에 의한 복사

alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true
</script>

참조에 의한 객체 비교:

<script>
let a = {};
let b = {}; // 독립된 두 객체

alert( a == b ); // false
</script>
  • obj1 > obj2 같은 대소 비교나 obj == 5 같은 원시값과의 비교에선 객체가 원시형으로 변환됩니다.

원시형 데이터의 비교:

<script>
let a = `hi`;
let b = `hi`;

alert( a == b ); // true. 값이 같기 때문에
</script>

객체 복사, 병합과 Object.assign

기존에 있던 객체와 똑같으면서 독립적인 객체를 만드는 방법들.

  • 객체를 복제해야 할 일은 거의 없습니다.
  • 정말 복제가 필요한 상황이라면 새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 복사하면 됩니다.
    예시:
<script>
let user = {
  name: "John",
  age: 30
};

let clone = {}; // 새로운 빈 객체

// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
for (let key in user) {
  clone[key] = user[key];
}

// 이제 clone은 완전히 독립적인 복제본이 되었습니다.
clone.name = "Pete"; // clone의 데이터를 변경합니다.

alert( user.name ); // 기존 객체에는 여전히 John이 있습니다.
</script>

Object.assign을 사용하는 방법. for in 문을 쓰지 않아도 됩니다.
문법:

<script>
Object.assign(dest, [src1, src2, src3...])
</script>
  • 첫 번째 인수 dest는 목표로 하는 객체입니다.
  • 이어지는 인수 src1, ..., srcN는 복사하고자 하는 객체입니다.
  • 객체 src1, ..., srcN의 프로퍼티를 dest에 복사합니다.
  • 주인공 dest를 반환합니다.

assign 메서드를 사용해 여러 객체를 하나로 병합하는 방법

<script>
let user = { name: "John" };

let permissions1 = { canView: true };
let permissions2 = { canEdit: true };

// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);

// now user = { name: "John", canView: true, canEdit: true }
</script>

목표 객체(user)에 동일한 이름을 가진 프로퍼티가 있는 경우엔 기존 값이 덮어씌워 집니다.

<script>
let user = { name: "John" };

Object.assign(user, { name: "Pete" });

alert(user.name); // user = { name: "Pete" }
</script>

예시를 실행하면 user에 있는 모든 프로퍼티가 빈 배열에 복사되고 변수에 할당됩니다.

<script>
let user = {
  name: "John",
  age: 30
};

let clone = Object.assign({}, user);
// 새 객체 생성과 동시에 user의 프로퍼티를 복사합니다.
</script>

⚠️중첩 객체는 복사 할 수 없습니다.
예시:

<script>
let user = {
  name: "John",
  sizes: { // 다른 객체에 대한 참조값
    height: 182,
    width: 50
  }
};

alert( user.sizes.height ); // 182
</script>
  • clone.sizes = user.sizes로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없습니다. user.sizes는 객체이기 때문에 참조 값이 복사되기 때문입니다.

  • clone.sizes = user.sizes로 프로퍼티를 복사하면 clone과 user는 같은 sizes를 공유하게 됩니다.

(객체를 복제해야 할 일은 거의 없기 때문에 중첩 객체 복사 방법은 나중에 작성하겠습니다.)


작성하면서 들은 노래:

메이플스토리 - 잊혀진 회랑, 루디브리엄, (구)커닝스퀘어
박재범 - drive

옛날엔 시간의 신전이랑 에우렐, 에레브 노래를 자주 들으면서 했는데
이상하게 루디브리엄 노래를 들으면 집중이 정말 잘된다.
특히 잊혀진 회랑은 최애 브금이 되었다.
꼭 들어보세요.

profile
저녁놀 마을 사람

0개의 댓글

관련 채용 정보