//call by value
//각자 값에 대한 저장공간을 가진다
var a = 5;
var b = a;
b++;
console.log(a);
console.log(b);
원시형 타입의 변수는 저장공간에 값이 저장된다.
따라서 b에 a를 할당했을 때 저장공간에 있는 값인 5가 할당된다.
5가 할당된 후 b의 값을 1 증가시켜도 a의 값에는 변동이 없다.
//call by reference
let obj1 = { name: "Kim", password: "123" };
let obj2 = obj1; //obj1의 주소가 들어간다.
obj2.password = "easy";
console.log(obj1);
console.log(obj2);
참조형 타입의 변수는 값 대신에 주소가 저장된다.
만약 obj1을 obj2에 대입하게 된다면 값이 들어간 것처럼 보여도
사실은 주소가 들어갔으므로 이제부터 obj1과 obj2는 같은 주소를 가지고 같은 공간을 가리킨다.
obj2의 password만 바꿨을 뿐인데, 두 변수 모두 값이 변경됐다.
참조형 변수 타입은 주소를 저장하므로 대입식을 사용하면 변수의 값을 복사할 수 없다.
얕은 복사 (Shallow clone)
얕은 복사는 이러한 참조형 변수의 값을 복사하기 위해 사용한다.
array
//array
var c = [1, 2, 3];
var d = c;
d.push(999);
console.log(d);
console.log(c);
배열은 참조형 이기 때문에 대입식을 사용하면 같은 주소를 가리키게 된다.
var c = [1, 2, 3];
var d = [].concat(c);
d.push(111);
console.log(d);
console.log(c);
배열타입의 내장 메서드인 concat을 사용해 d에 할당해 봤다.
concat을 사용해 복사된 배열 d는 c와 별개의 주소를 가지게 된다.
object
//obj
let obj = { a: "a", b: "b", c: { deep: "try copy" } };
//shallow clone
let clone = Object.assign({}, obj);
let clone2 = { ...obj };
obj.b = 5;
console.log(obj);
console.log(clone);
console.log(clone2);
이번에는 객체를 내장메서드 assign과 ...(spread)을 사용해 얕은 복사를 진행했다.
전개 연산자인 spread는 배열을 복사할 때도 사용할 수 있다.
얕은 복사는 객체에 들어있는 주소값을 한번 타고 들어가서 그 공간에 있는 값들을 가져와서 복사한다.
깊은 복사 (Deep clone)
let obj = { a: "a", b: "b", c: { deep: "try copy" } };
//shallow clone
let clone = Object.assign({}, obj);
let clone2 = { ...obj };
obj.b = 5;
console.log(obj);
console.log(clone);
console.log(clone2);
obj.c.deep = "hahahah";
console.log(obj);
console.log(clone);
console.log(clone2);
얕은 복사는 주소값을 한번까지밖에 타고 들어가지 않기 때문에
만약 주소층이 둘 이상이라면 그 이상부터는 다시 주소값을 가져오고
같은 공간을 가리키게 된다.
c속성에 저장된 객체의 deep속성의 주소값이 얕은 복사로 복사되었기 때문에
c는 모두 같이 변동된다.
//deep clone
let superClone = JSON.parse(JSON.stringify(obj));
obj.c.deep = "heheh";
console.log(obj);
console.log(clone);
console.log(superClone);
이럴 땐 어쩔 수 없이 모든 주소층을 다 뒤져서 통째로 복사해오는 수밖에 없다.
JSON 내장 메서드를 사용해 obj를 문자열로 변환하고 파싱한 결과를 변수에 저장했다.
진정한 의미의 복사다.
깊은 복사가 된 객체는 obj의 변동값에 영향을 안 받는 것을 확인할 수 있다.
하지만 이러한 깊은 복사는 배열이 깊어지거나 데이터의 양이 많아질수록 비효율적인 행위가 될 수 있으니
정말 필요한 경우가 아니라면 사용을 지양하거나 본인의 상황에 맞는 함수를 제작해 복사하는 것이 좋다.
'Front-end > JavaScript' 카테고리의 다른 글
JS Type 4편 - 동적 타입(static&dynamic type) (0) | 2022.12.31 |
---|---|
JS Type 3편 - type Coercion(==, === 차이) (0) | 2022.12.30 |
JS Type 1편 - 자바스크립트 타입 종류(primitive, non-primitive) (0) | 2022.12.26 |
JS 동작원리 10편 - call, apply, bind (0) | 2022.12.24 |
JS 동작원리 9편 - Scope(lexical & dynamic)와 this (0) | 2022.12.19 |