JavaScript - copy by value & reference

윤수빈·2024년 7월 29일
0

값에 의한 복사, 참조에 의한 복사는 어떤 언어든간에 명확하게 알고 넘어가야 할 만큼 중요한 내용이다.


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가 나오게된다.


copy by value 값 비교

출력에서도 보았듯이 value의 경우 clone 만 값이 변경되고, 기존 값은 그대로인 것을 볼 수 있다.

originals 라는 메모리 공간과 clone 이라는 메모리 공간이 다르기 때문에
그 공간에 담긴 값이 별도로 정의된 것을 알 수 있다.

때문에 clone 메모리 공간에 담긴 value가 변경되어도 기존 값에는 영향을 주지 않는 것이다.

결국 기존 값의 value와 clone의 value 는 서로 다르기 때문에 false가 출력된 것이다.

copy by reference

여기서는 기존 값을 변경하였고, 이후 clone에 담긴 값도 같이 변경된 것을 볼 수 있다.

그 이유는 객체(Object)의 경우 선언이 되면 객체를 담는 공간과 내용물의 메모리 공간이 별도로 할당이 된다.

예를 들어,
originalObj의 메모리 주소가 0x000001 이라면,
originalObj 에 담긴 값은는 메모리 주소가 0x000003 으로 별도로 할당된다.

primitive 값과 다르게 하나의 메모리 공간에 변수 이름과 value가 담기지 않는다.

그럼 originalObj 메모리 공간안에 담긴 값은 무엇이지?

originalObj 안에 담긴 값은 바로 originalObj 에 담긴 값 이 할당된 메모리 주소 0x000003 이 담긴다.

때문에 cloneObjoriginalObj 의 value 값을 가르키는 메모리주소 0x000003을 복사하게 되고 originalObj의 값을 변경해도 cloneObj 까지 같이 변경이 되는 것이다.


reference는 그럼 값이 동일하기 때문에 당연히 true가 나오는 것 아닌가?

이 부분은 아래 코드로 값이 동일해도 동일하지 않은 것을 확인할 수 있다.

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는 배열 함수 중 하나로 배열을 복제하는 기능을 가지고있다.

다음 특징을 가진다.

  1. copy by value로 오브젝트를 복제
  2. 하지만 다른 메모리값에 할당되기 때문에 기존 값과는 다름
  3. 또한, Spread를 사용하면 복제하면서 값을 추가하거나 변경이 가능!
  4. spread syntax를 이용한 shallow copy 이다.

복제한 값을 기존 값과 비교한다면

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 }

profile
정의로운 사회운동가

0개의 댓글