-
얕은 복사
const obj = { x: 1 }; const copy = obj; console.log(copy === obj); //true
위의 예시처럼 객체를 할당한 변수(
obj
)를 다른 변수(copy
)에 할당하는 것 -
깊은 복사
const val = 1; const copy = val; console.log(copy === val); //true
위의 예시처럼 원시(primitive) 타입의 값을 할당한 변수(
val
)를 다른 변수(copy
)에 할당하는 것
-
원시 타입
- 숫자 타입
BigInt
타입- 문자열 타입
- 불리언 타입
undefined
타입: var 키워드로 선언된 변수에 암묵적으로 할당되는 값null
타입: 값이 없다는 것을 의도적으로 명시할 때 사용하는 값- symbol 타입: ES6에서 추가된 7번째 타입
-
객체 타입
- 객체, 함수, 배열 등
- 객체, 함수, 배열 등
이 둘은 크게 세 가지 측면에서 다르다.
원시 값
(원시 타입의 값)은 변경 불가능한(immutable) 값
객체(참조)타입의 값,객체
는 변경 가능한(mutable) 값원시 값을 변수에 할당
하면 변수(확보된 메모리 공간)에는 실제 값이 저장객체를 변수에 할당
하면 변수(확보된 메모리 공간)에는 참조 값이 저장- 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달, 이를 값에 의한 전달(pass by value)이라 함
객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달, 이를 참조에 의한 전달(pass by reference)이라 함
-
원시 값
-
변경 불가능한 값
원시 값 자체를 변경할 수 없다는 것이지 변수의 값을 변경할 수 없다는 것이 아니다.
변수는 언제든 재할당을 통해 변수 값을 변경할 수 있다. (상수는 재할당이 금지된 변수)
원시 값을 할당한 변수에 새로운 원시 값을 재할당하면 메모리 공간에 저장되어 있는 재할당 이전의 원시 값을 변경하는 것이 아니라,
새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장하고,
변수는 새롭게 재할당한 원시 값을 가리킨다.
이때 변수가 참조하던 메모리 공간의 주소가 바뀐다. 원시 값이 변경 불가능하기 때문에 메모리 공간의 주소를 변경한 것.
이러한 특성으로 데이터의 신뢰성을 보장한다. -
원시 값을 변수에 할당 시 변수에는 실제 값이 저장
객체에는 참조 값(메모리 공간 주소)이 저장된다.
-
문자열
원시 값인 문자열 역시 변경 불가능한 값이지만 유사 배열 객체이다.
그래서 인덱스로 접근 가능하고,length
프로퍼티,for문
도 사용 가능하지만
객체처럼 값을 변경하는건 안 된다. -
값에 의한 전달
var score = 80; var copy = score; // copy 변수에는 score 변수의 값 80이 복사되어 할당된다. console.log(score, copy); //80 80 console.log(score === copy); //true score = 100; // score 변수와 copy 변수의 값은 다른 메모리 공간에 저장된 별개의 값 // score 변수의 값을 변경해도 copy 변수의 값에는 어떠한 영향도 주지 않는다. console.log(score, copy); //100 80 console.log(score === copy); //false
두 변수(
score
,copy
)의 값은 같겠지만 서로 참조하는 메모리 주소가 달라서
어느 한 변수에 재할당을 통해 값을 변경해도 그 변수만 변하지 다른 하나의 변수는 변하지 않는다.
그리고 자바스크립트는 그렇게 할당했을 때 새로운 똑같은 값을 생성(복사)해서 메모리 주소를 전달한다.
-
-
객체
-
변경 가능한 값
재할당 없이 직접 변경 가능하다. 재할당 없이 프로퍼티 동적 추가, 프로퍼티 값 갱신, 프로퍼티 삭제 가능
var person = { name: 'Lim' }; person.name = 'Kim'; // 프로퍼티 값 갱신 person.address = 'Seoul' // 프로퍼티 동적 생성 console.log(person); //{name: "Kim", address: "Seoul"}
-
참조에 의한 전달
-
객체를 프로퍼티 값으로 갖는 객체의 경우
얕은 복사
는 한 단계까지만 복사하는 것을 말하고,
깊은 복사
는 객체에 중첩되어 있는 객체까지 모두 복사하는 것을 말한다.
const o = { x: { y: 1 } };
// 얕은 복사
const c1 = { ...o };
console.log(c1 === o); //false
console.log(c1.x === o.x); //true
// 깊은 복사 (lodash의 cloneDeep 사용)
const _ = require('lodash');
const c2 = _.cloneDeep(o);
console.log(c2 === o); //false
console.log(c2.x === o.x); //false
얕은 복사와 깊은 복사로 생성된 객체는 원본과는 다른 객체다. (원본과 참조 값이 다른 별개의 객체)
각각의 복사는 원본과 참조 값이 다른 별개의 객체를 복사하는 것은 같지만, 객체에 중첩된 객체를 복사하는 것에 차이가 있다.
얕은 복사
는 객체에 중첩되어 있는 객체의 경우 참조 값을 복사하고,
깊은 복사
는 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전한 복사본을 만든다는 차이가 있다.
- 책 <모던 자바스크립트 Deep Dive>