원시 데이터 : String, Number, Boolean, undefined, null
let x = 1;
let y = 4;
console.log(x, y, x === y);
// 1 4 false
x = y;
console.log(x, y, x === y);
// 4 4 true
y = 7;
console.log(x, y, x === y);
// 4 7 false
let z = 4;
console.log(x, y, z, x === z);
// 4 7 4 true
참조형데이터 : Object, Array, Function (불변하지 않음)
let a = { k: 1 };
let b = { k: 1 };
console.log(a, b, a === b);
// {k: 1} {k: 1} false
a.k = 55;
b = a;
console.log(a, b, a === b);
// {k: 55} {k: 55} true
a.k = 33;
console.log(a, b, a === b);
// {k: 33} {k: 33} true
let c = b;
console.log(a, b, c, a === c, b === c);
// {k: 33} {k: 33} {k: 33} true true
참조형데이터의 경우 참조하고 있는 참조값을 변경하면 같은 참조를 가리키는 변수들도 전부 변경이 될 수 있다.
→ 즉 참조형 데이터에서는 할당 연산자를 이용하면서 의도하지 않았던 데이터 값의 변경이 발생될 수 있다.
생긴 것이 같아도 같은 데이터가 아닐 수 있음에 유의하자.
따라서 각자의 독립적인 데이터 값으로 관리하고 싶으면 메모리상에서 분리 해서 사용되어야 한다. 이 때 '복사'를 이용할 수 있다. (얕은복사 & 깊은복사)
Array.from, concat, slice, spread(...), Object.assign
✍️ 표면만 복사한다는 개념으로 이해하자.
const user = {
name: "seul",
age: 10,
email: ["seul@gmail.com"],
bloodType: "O",
};
const copyUser = Object.assign({}, user); // 1)
console.log(user, copyUser);
console.log(copyUser === user); // false
Object.assign()
메서드를 이용해서 첫번째 인수자리에는 빈 객체{}
데이터를 넣고, 두번째 인수로는 복사한 user
라는 데이터를 넣어준다.// 데이터 수정해보기
const copyUser = Object.assign({}, user);
console.log(user, copyUser);
console.log(copyUser === user); // false
user.age = 12;
console.log(user); // 변경되었다
console.log(copyUser); // 변경되지 않았다 // 2)
user.age
데이터를 변경해도 copyUser
데이터에는 영향을 주지 않게 되었다.const user = {
name: "seul",
age: 10,
email: ["seul@gmail.com"],
bloodType: "O",
};
const copyUser = { ...user }; // 1)
console.log(user, copyUser);
console.log(copyUser === user); // false
user.age = 12;
console.log(user); // 변경되었다
console.log(copyUser); // 변경되지 않았다
user.email.push("abc@naver.com");
console.log(user.email === copyUser.email); // 2) true
user.email = "xyz.naver.com";
console.log(user.email === copyUser.email); // 3) false
1) 빈객체 데이터에 user라는 객체가 가지고 있는 데이터를 전개해서 넣는다.
2) user에 넣은 데이터가 copyUser에도 똑같이 적용된 것을 볼 수 있다.
- { ...user }
를 통해서 표면만 복사한 상태이므로 그 속 내용은 복사가 되지 않은 상태이다. 따라서 객체 안의 모든 데이터들도 복사(깊은복사)를 해야 한다.
3) 2)같은 경우는 배열 데이터이기때문에 마찬가지로 데이터주소를 참조한다. 즉 속 내용은 복사가 되지 않은 상태이기때문에 발생한 문제처럼 보였다.
3)처럼 그냥 일반 문자형 데이터를 넣어주면 어떻게 되는지 궁금해서 작성해 보았다.🤔
아래 사진처럼 user
데이터는 변경되었지만, copyUser
는 변경되지 않음을 알 수 있었다!
✍️ 내부에 있는 모든 참조관계까지 새로운 메모리로 복사한다는 개념으로 이해하자.
.cloneDeep() :
.clone()
과 비슷하지만 재귀적으로 값을 복사한다. (반복실행하면서 모든 값들을 복제한다. → 깊은 복사가 가능해진다. )
: 배열데이터라는 껍데기만 복사한 것이 아니고 내부에 들어있는 새로운 참조형 데이터인 객체 데이터까지 전부 복사를 해서 새로운 메모리로 할당했다. 그러므로 내부의 값을 일치연산자로 비교를 해도 false가 나온다.
import _ from "lodash";
const user = {
name: "seul",
age: 10,
email: ["seul@gmail.com"],
bloodType: "O",
};
const copyUser = _.cloneDeep(user); //1)
console.log(user, copyUser);
console.log(copyUser === user); // false
user.age = 12;
console.log(user); // 변경되었다
console.log(copyUser); // 변경되지 않았다
user.email.push("abc@naver.com");
console.log(user.email === copyUser.email);
user
객체를 넣는다.✍️
대표적인 참조형 데이터인 객체, 배열 등을 복사할 때는 그 내부에 또다른 참조형 데이터가 없다는 전제 하에서는 손쉽게 얕은 복사(Shallow copy)를 활용하고, 특정한 참조데이터 내부에 또 다른 참조형 데이터가 있다면 깊은 복사(Deep copy)를 고려하자.🤔