값에 의한 복사, 참조에 의한 복사는 어떤 언어든간에 명확하게 알고 넘어가야 할 만큼 중요한 내용이다.
1. 정의
copy by value - 값에 의한 전달로 복사
copy by reference - 참조에 의한 전달로 복사
기본적으로 복사를 하게될 때,
1. 모든 primitive 값은 copy by value 이다.
*primitive : 오브젝트를 제외한 생성된느 모든 데이터 타입
2. 객체는 copy by reference 이다.
2. copy by value
예를 들어, primitive 값
// copy by value
let originals = '나는 오리지널';
let clone = originals;
console.log(originals);
console.log(clone);
clone += ' 사실 클론';
console.log('--------------------');
console.log(originals);
console.log(clone);
의 출력 결과는 아래와 같다.
나는 오리지널
나는 오리지널
나는 오리지널
나는 오리지널 사실 클론
3. copy by reference
그리고, 객체(object) 값
// copy by reference
let originalsObj = {
name: '홍길동',
age: 24
};
let cloneObj = originalsObj;
console.log('--------------------');
console.log(originalsObj);
console.log(cloneObj);
originalsObj['age'] = 30;
console.log('--------------------');
console.log(originalsObj);
console.log(cloneObj);
의 출력 결과는
{ name: '홍길동', age: 24 }
{ name: '홍길동', age: 24 }
--------------------
{ name: '홍길동', age: 30 }
{ name: '홍길동', age: 30 }
4. copy by value 와 reference 값 비교
위에서 다룬 내용
1. 기존 값 선언 및 정의
2. clone 변수 선언 및 기존 값 복사
3. value는 clone 값을 변경, reference는 기존 값을 변경
4. 기존 값과 clone 값을 출력
그러면 위 clone 값을 기존값과 비교해보면 어떻게 나올까?
// copy by value 와 copy by reference 의 값 비교
console.log(originals === clone);
console.log(originalsObj === cloneObj);
출력 결과는
false
true
으로
copy by value 는 false
copy by reference 는 true가 나오게된다.
출력에서도 보았듯이 value의 경우 clone 만 값이 변경되고, 기존 값은 그대로인 것을 볼 수 있다.
originals 라는 메모리 공간과 clone 이라는 메모리 공간이 다르기 때문에
그 공간에 담긴 값이 별도로 정의된 것을 알 수 있다.
때문에 clone 메모리 공간에 담긴 value가 변경되어도 기존 값에는 영향을 주지 않는 것이다.
결국 기존 값의 value와 clone의 value 는 서로 다르기 때문에 false
가 출력된 것이다.
여기서는 기존 값을 변경하였고, 이후 clone에 담긴 값도 같이 변경된 것을 볼 수 있다.
그 이유는 객체(Object)의 경우 선언이 되면 객체를 담는 공간과 내용물의 메모리 공간이 별도로 할당이 된다.
예를 들어,
originalObj
의 메모리 주소가 0x000001 이라면,
originalObj 에 담긴 값은
는 메모리 주소가 0x000003 으로 별도로 할당된다.
그럼 originalObj
메모리 공간안에 담긴 값은 무엇이지?
originalObj
안에 담긴 값은 바로 originalObj 에 담긴 값
이 할당된 메모리 주소 0x000003 이 담긴다.
때문에 cloneObj
는 originalObj
의 value 값을 가르키는 메모리주소 0x000003을 복사하게 되고 originalObj
의 값을 변경해도 cloneObj
까지 같이 변경이 되는 것이다.
이 부분은 아래 코드로 값이 동일해도 동일하지 않은 것을 확인할 수 있다.
originalsObj = {
name: '홍길동',
age: 24
};
cloneObj = {
name: '홍길동',
age: 24
};
console.log('--------------------');
console.log(originalsObj === cloneObj);
이는 originalObj
의 value를 가리키는 메모리주소와 cloneObj
의 value를 가리키는 메모리주소가 다르기 때문에 false
가 출력된다.
추가로,
const man1 ={
name: '홍길동',
height: 170
}
const man2 = man1;
const man3 = {
name: '홍길동',
height: 170
}
console.log('--------------------');
console.log(yujin1 === yujin2);
console.log(yujin1 === yujin3);
console.log(yujin2 === yujin3);
의 결과를 예상해보자.
true // 같은 메모리주소를 가리키고 있기 때문에
false // 가리키는 메모리주소가 서로 다르기 때문에
false // 가리키는 메모리주소가 서로 다르기 때문에
가 될 것이다.
5. Spread Operator
JavaScript 공부 - 02 에서 복제에 대해 얘기할 때 덧붙여 작성한다.
Spread Operator는 배열 함수 중 하나로 배열을 복제하는 기능을 가지고있다.
다음 특징을 가진다.
복제한 값을 기존 값과 비교한다면
const man1 ={
name: '홍길동',
height: 170
}
const man2 = {
...man1
};
console.log(man2);
console.log(man2 === man1);
copy by value로 복제하기 때문에 false
가 된 것을 알 수 있다.
복제하면서 값을 추가하는 것은 아래처럼 가능하다.
const man3 = {
year: 1997,
...man1,
};
console.log(man3);
{ year: 1997, name: '홍길동', height: 170 }