JS에서 변수에는 크게 객체(객체, 배열)와 객체가 아닌 원시값으로 구분할 수 있다. 객체가 아닌 변수 값에는 문자, 숫자, 그리고 boolean 등이 있으며, 이러한 원시값에는 참조 의 개념이 존재하지 않는다. (c 에서는 포인터로 참조했던 기억이..)
그러나, 객체에는 데이터 불변성을 유지시키기 위해 참조 의 개념이 존재한다. 객체에서 원시값처럼 =
을 통해 복사하게 된다면, 복사가 아닌 참조가 된다.
이와 같이, 참조의 개념으로 인해 JS에서는 객체의 복사본을 만든 뒤, 복사본에 대해서 수정할 때는 주의할 점이 여러가지 있다.
let arr = [1,2,3,4];
let copy = arr;
copy[0] = 'a';
console.log(arr); // ['a',2,4,5]
console.log(arr); // ['a',2,4,5]
console.log(arr === copy) // true
위와 같이, 객체의 복사본을 수정하게 되면 원본도 함께 수정이 된다. 그 이유는 객체는 값을 복사하는 것이 아니라, 참조 를 하기 때문이다.
또한, 이러한 참조 성질으로 인해 arr과 copy는 완전히 동일한 객체가 되면서 arr===copy
는 true가 되는 것이다.
assign 첫번째 인자 값(대상 객체)에 빈 객체를 준다면, 두번 째 값에 들어오는 출처 객체가 그대로 복사된다.
let obj = { name : 'jun', age : 18 };
let copy = Object.assign({}, obj);
console.log(obj === copy) // false (참조가 아닌 복사이므로)
copy.name = 'kim';
console.log(obj); // { name : 'jun', age : 18 }
console.log(copy); // { name : 'kim', age : 18 }
let obj1 = { name : 'jun', age : 18 };
let obj2 = { age : 26, job : 'student' };
Object.assign(obj1, obj2); // {name: 'jun', age: 26, job: 'student'}
비교적 최신 문법(ES6)인 spread 연산자는 간단한 코드 길이와 메소드 호출이 따로 필요 없어 빠른 처리가 가능하다.
Spread는 '펼치다'라는 뜻을 가지고 있다. 말 그대로 연산자 뒤의 객체를 펼쳐서 복사해 준다고 생각하면 편하다.
let obj = { name : 'jun', age : 18 };
let copy = { ...obj };
console.log(obj === copy) // false (참조가 아닌 복사이므로)
copy.name = 'kim';
console.log(obj); // { name : 'jun', age : 18 }
console.log(copy); // { name : 'kim', age : 18 }
slice와 concat 함수에 인자값을 주지 않음으로써, 배열의 얕은 복사가 가능하다.
let arr = [1,2,3];
let copy1 = arr.concat();
let copy2 = arr.slice();
console.log(arr===copy1, arr===copy2) // false false
copy1[0] = 'a';
copy2[2] = 'c';
console.log(arr) // [1,2,3]
console.log(copy1) // ['a',2,3]
console.log(copy2) // [1,2,'c']
let arr = [0,1,2,3,4,5];
console.log(arr.slice(2,4)); // [2,3]
console.log(arr.slice(3)); // [3,4,5]
let arr = [0,1,2];
let arr2 = [3,4,5];
console.log(arr.concat(arr2)); // [0,1,2,3,4,5]
위의 객체와 같이 spread 연산자를 이용하여 얕은 복사가 가능하다.
let arr = [1,2,3];
let copy = [...arr];
console.log(arr===copy) // false
copy[0] = 'a';
console.log(arr) // [1,2,3]
console.log(copy) // ['a',2,3]]