var p1 = 1;
p1
의 값 1
은 메모리 어느공간에 저장이된다.
var p2 = 1;
p2
의 값은 p1
에 의해 저장된 1
에 의해 p1
의 값을 가르킨다
그렇게되면 p1
과 p2
는 같은 값을 가르키게 된다.
비교동등연산자로 확인해보면
p1===p2 => true
같은 값인 것을 확인할 수있다.
객체 타입일 경우 어떻게 될까
var o1 = {color: 'red'};
var o2 = {color: 'red'};
먼저 비교동등연산자로 확인해보면
o1===o2 => false
false
가 출력된다. 두 변수는 같지 않다는 의미이다
위에서 살펴본 숫자형인 원시타입 결과를 비춰보면
같지 않다는 의미는 두 변수의 값은 각각 다른 메모리 공간에 저장이 된다는 말이다
객체형은
color
의 프로퍼티값이 언제든 바뀔수있다. 그렇기 때문에 각각 다른 메모리 공간에 값이 저장이 된다.
원시타입은 그 값이 변하지 않는다.1 = 1
이다1 = 2
가 될 수 없다. 그래서 변수의 값들이 같으면 하나의 메모리 공간만 사용을 한다. 이것을immutability 불변성
이라고 한다.
var p1 = 1;
var p2 = 1;
var p3 = p1;
var p3 = p1;
에 의해 p3
의 값은 1
이 된다.
p1,p2,p3
모두 1
을 가르키고 있다.
여기서 var p3 = 2;
되면
p3
는 새로운 메모리 공간에 2
를 저장하게 된다.
객체타입을 살펴보자
var o1 = {color: 'red'};
var o2 = {color: 'red'};
var o3 = o1
여기서 o3
의 값을 blue
로 바꾸고
o1,o2,o3
출력해보면
o3.color = 'blue';
console.log(o1,o2,o3);
=> {color: "blue"} {color: "red"} {color: "blue"}
원시타입과는 다르게 o1
과 o3
의 값이 같이 변경되있다.
두 값이 같이 변경되는것을 의도를 했다면 괜찮겠지만
그렇지 않는 입장에서는 곤란 할 수 있다.
이런경우 Object.assign()
을 사용하면 된다.
var o1 = {color: 'red'};
var o2 = {color: 'red'};
var o3 = Object.assign({},o1);
o3.color = 'blue';
console.log(o1,o2,o3);
=> {color: "red"} {color: "red"} {color: "blue"}
o1
의 값은 불변하고 o3
의 값만 변경되게 된다.
var o1 = {color: 'red', score: [1,2]};
o1
값으로 객체를 주었고 score
의 프로퍼티값을 객체로 주었다.
객체 안에 객체가 있는 경우 메모리에 어떻게 저장이 될까
먼저 {color: 'red', score: }
의 값이 메모리에 저장이되고 프로퍼티값이 배열인 객체 [1,2]
값은 따로 저장이 된다.
o1
을 복제해서 o2
의 값을 만들었다.
var o2 = Object.assign({}, o1);
console.log(o2);
=>{color: 'red', score: [1,2]};
메모리에는 어떻게 저장이 될까.
o2
에 프로퍼티는 다른 공간에 저장이 된다. 하지만 o2
프로퍼티값 중에 object 형
은 새로운 공간에 저장되지 않고 복제를 한 o1
의 값을 가르킨다.
새로운 저장공간에 저장하려면 score
의 객체 값을 복제해야한다.
코드로 살펴보자
var o1 = {color: 'red', score: [1,2]};
var o2 = Object.assign({}, o1);
o1을 통해 o2를 복제했고
o2.score.push(3);
복제한 o2 score값에 3을 추가하고 o1,o2를 출력하면 다음과 같이 결과값이 나온다.
{ color: 'red', score: [ 1, 2, 3 ] } { color: 'red', score: [ 1, 2, 3 ] }
o2
에서 o1
의 score
값 객체를 복제하지 않았기 때문에 o2
의 값을 바꿨을때 o1
의 값도 같이 바뀌게 된다.
o2
의 score
값만 바꾸려고 했는데 둘다 바뀌는 곤란한 상황이 발생할 수있다.
그러면 push
말고 concat
을 사용하면 된다.
push
는 인자를 추가하면 새로운 배열을 만들어내는 반면concat
은 배열을 복제하고 그 배열에 인자를 추가한다. 결국 배열을 복제하는 효과를 가지고있다var o1 = {color: 'red', score: [1,2]};
var o2 = Object.assign({}, o1);
o1을 통해 o2를 복제했고
o2.score = o2.score.concat();
concat을 통해 score배열을 복제하고
o2.score.push(3);
score 배열에 3을 추가하고 o1,o2를 출력하면
{ color: 'red', score: [ 1, 2] } { color: 'red', score: [ 1, 2, 3 ] }
o1의 값을 불변하고 o2의 값만 바뀐것을 볼 수 있다.
메모리 저장공간을 살펴보면
o1
, o2
모두 {color: 'red', score: }
값이 각각 저장공간에 저장되었고, score
의 객체인 배열은 o1
을 따르는 한곳에만 저장된다. 그리고 concat
에 의해 복제된 score
의 값은 각각 다른 저장공간에 저장된다. 그리고 o2.score
값을 변경하게 되면 o1.score
은 변경되지 않고 o2
의 값만 바뀌게 된다.
function fn(person){
person.name='lee';
}
person을 인자로 같은 함수 fn을 선언했다
var o1 = {name: 'kim'}
객체를 갖는 o1을 선언했다
fn(o1);
fn함수의 인자로 o1을 넣었고 출력을 하게되면 다음과 같은 결과가 나온다
console.log(o1);
=> { name: 'lee' }
fn()
의 동작 방법을 아는 사람이 사용할 때는 편리 할 수있다.
하지만 방법을 모르는 사람이 fn()
을 사용 하였을때 o1
의 값이 바뀌는 사고가 발생 할 수 있다. 이처럼 의도를 하지 않았는데 발생하는 효과는 좋은 코드가 아니다.
다시 코드를 작성해보면
function fn (person){
person = Object.assign({}, o1);
person.name = 'lee';
return person;
}
o1이 바뀌지 않게 하기위해 o1을 복제하고
복제한 값을 lee로 수정하고
리턴한다.
var o1 = {name: 'kim'};
var o2 = fn(o1);
console.log(o2);
=> { name: 'lee' }
function fn (person){
person.name = 'lee';
}
var o1 = {name: 'kim'};
var o2 = Object.assign({}, o1);
fn(o2);
console.log(o2);
=> { name: 'lee' }
두 가지 방식으로 작성할 수 있다.