Boolean
, Null
, Undefined
, String
, Number
)을 가지고 있습니다. 우리는 이러한 데이터 타입을 원시 타입(Primitive Types) 이라고 부릅니다.Array
, Function
, Object
)도 가지고 있습니다. 사실 이 3가지는 크게 보자면 전부 객체(Objects)
로 볼 수 있습니다.원시값은 값을 복사할 때, 복사된 값을 다른 메모리에 할당하므로 원래 값과 복사된 값이 서로에게 영향을 미치지 않습니다.
const a = 1;
let b = a;
b = 2;
console.log(a); // 1
console.log(b); // 2
b
는 a
의 값을 복사합니다. b
는 a
와 동일한 값 1
을 갖게 됩니다.b
는 a
와는 다른 메모리 공간에 할당됩니다. 즉, b
는 a
와 독립된 값을 갖게 됩니다.b
에 새로운 값 2
를 할당합니다. 이는 b
의 값을 변경하지만, a
의 값에는 영향을 미치지 않습니다.그러나 참조 값은 변수가 객체의 주소를 가리키는 값이므로, 복사된 값(주소)은 동일한 객체를 가리킵니다.
const num = [1, 2, 3];
const numCopy = num; // 얕은 복사
numCopy.push(4);
const result = num === numCopy;
console.log(num); // 출력: [ 1, 2, 3, 4 ]
console.log(numCopy); // 출력: [ 1, 2, 3, 4 ]
console.log(result); // true
num
은 실제로 값을 가진게 아니라 배열([1, 2, 3]
)이 위치한 메모리의 주소를 가리킵니다.numCopy
변수는 num
변수와 동일한 메모리 주소를 참조합니다. 따라서 num
과 numCopy
는 같은 배열을 참조하게 됩니다. 이 경우, 이는 얕은 복사입니다.num
에도 영향을 미칩니다.numCopy
를 통해 배열에 4
를 추가하면, 실제로는 같은 메모리 주소를 참조하고 있기 때문에 num
도 영향을 받아 [1, 2, 3, 4]
로 변경됩니다.num
과 numCopy
는 동일한 메모리 주소를 참조하고 있기 때문에, ===
연산자는 true
를 반환합니다.Object.assign()
은 자바스크립트에서 사용되는 내장 함수 중 하나입니다. 이 함수는 한 개 이상의 소스 객체로부터 대상 객체로 속성을 복사 할 때 사용됩니다.
const user = {
name: "jinwoo",
age: 123,
email: ["1234@gmail.com"],
};
// 원본 객체를 복사해서 새로운 객체를 생성
const copy = Object.assign({}, user);
console.log(copy === user); // false
// 복사본을 변경
copy.age = 900;
copy.email.push("5678@gmail.com");
console.log("user", user);
console.log("copy", copy);
console.log(user.email === copy.email); // true
/*
false
user {
name: 'jinwoo',
age: 123,
email: [ '1234@gmail.com', '5678@gmail.com' ]
}
copy {
name: 'jinwoo',
age: 900,
email: [ '1234@gmail.com', '5678@gmail.com' ]
}
true
*/
Object.assign({}, user)
를 사용하면 객체의 첫 번째 레벨만 복사되어 새로운 객체가 생성되는데, 이를 얕은 복사(shallow copy)라고 합니다. 객체의 속성 중에서 배열이나 다른 객체와 참조 타입의 속성은 원본 객체와 복사된 객체가 같은 메모리 주소를 참조하게 됩니다. copy.email.push("5678@gmail.com")
코드를 실행하면 원본 객체의 email 속성도 변경되었고, user.email === copy.email
의 결과가 true
가 나온 것입니다. 이런 현상을 피하려면 깊은 복사(deep copy)를 사용해야 합니다....
)배열이나 객체의 요소들을 개별적으로 분리하여 다른 배열이나 객체에 복사하는 데 사용됩니다.
const user = {
name: "jinwoo",
age: 123,
email: ["1234@gmail.com"],
};
// 원본 객체를 복사해서 새로운 객체를 생성
const copy = { ...user };
console.log(copy === user); // false
// 복사본을 변경
copy.age = 900;
copy.email.push("5678@gmail.com");
console.log("user", user);
console.log("copy", copy);
console.log(user.email === copy.email); // true
/*
false
user {
name: 'jinwoo',
age: 123,
email: [ '1234@gmail.com', '5678@gmail.com' ]
}
copy {
name: 'jinwoo',
age: 900,
email: [ '1234@gmail.com', '5678@gmail.com' ]
}
true
*/
lodash
라이브 러리의 cloneDeep
함수를 사용해서 깊은 복사를 진행했습니다. _.cloneDeep()
함수는 재귀적으로 객체를 순회하면서 모든 하위 객체들을 새로운 객체로 복사한다고 합니다. 그래서 원본 객체의 속성을 변경해도 복사본 객체에 영향을 주지 않는다고 합니다. 아직 재귀함수에 대해 배우지 않아서 재귀함수를 배우고 재귀관련 내용을 추가하겠습니다.
import _ from "lodash";
const user = {
name: "jinwoo",
age: 123,
email: ["1234@gmail.com"],
};
// 원본 객체를 복사해서 새로운 객체를 생성
const copy = _.cloneDeep(user);
console.log(copy === user); // false
// 복사본을 변경
copy.age = 900;
copy.email.push("5678@gmail.com");
console.log("user", user);
console.log("copy", copy);
console.log(user.email === copy.email); // false
/*
false
user { name: 'jinwoo', age: 123, email: [ '1234@gmail.com' ] }
copy {
name: 'jinwoo',
age: 900,
email: [ '1234@gmail.com', '5678@gmail.com' ]
}
false
*/
console.log(copy === user)
의 결과는 false
입니다. 이는 깊은 복사를 통해 복사된 객체와 원본 객체가 서로 다른 객체임을 의미합니다. console.log(user.email === copy.email)
의 결과도 false
입니다. 깊은 복사를 통해 복사된 객체들이 서로 다른 배열의 메모리 주소를 참조 하고있습니다.