var num = 1;
var num2 = num;
num = 2;
console.log(num2) // 1
🤨?
var room = {
table: 1
};
var room2 = room;
room.table = 2;
console.log(room2.table) // 2;
🤨??
둘의 차이점은 첫번째는 원시값(primitive)이고 다른쪽은 참조값(reference)라는 것.
원시값 primitive value/type
은 메모리에서 스택 stack이라는 공간에 값을 저장하게 됨.
스택에서는 비교적 짧은 데이터들을 저장하고 빨리 불러오며, '스택'이라는 이름답게 데이터가 하나하나 위로 쌓이게 됨.
var num = 1일때, 스택에 1이라는 값을 제일 아래 칸에 저장함.
그 후 var num2 = num을 하게되면 num2는 원래 스택에 있던 1을 가리키는게 아니고,
1을 복사해서 그 뒤에 또다른 1을 스택쌓음.
그러다보니 num의 값을 2로 바꿔도 맨 아래있던 1이 2로 바뀔뿐이지,
그 윗칸에 있는 num2의 값인 1은 그대로 1로 남아있는거임.
참조값 reference value/type
은 메모리에서 힙 heap이라는 공간에 값을 저장하게 됨.
힙에서는 더 많은 양의 데이터를 저장하고 접근에 약간 시간이 걸리며, 데이터가 랜덤하게 자리를 잡고있음.
var room = {table: 1}일때, 힙에 {table: 1}이라는 값을 저장함.
그리고 room은 어떤 주소(ref)를 통해 {table: 1}이라는 실제 값으로 접근하게 됨.
이때 var room2 = room을 하게되면 room2 또한 어떤 주소(ref)를 통해 {table: 1}이라는 값으로 접근하게 됨.
둘다 결국 하나의 같은 값으로 접근하게 되는것임.
그러다보니 room의 값을 {table: 2}로 바꾸면,
둘다 같은 값을 가리키는 원본 값이 변했기때문에 둘다 값이 변하는 것임.
원시값도 reference?
위 설명을 요약하자면 원시값은 a = b를 하는 순간 b가 a의 값을 복사하기때문에 a가 바뀌어도 영향을 안받고,
참조값은 a = b를 하는 순간 같은 ref로 값을 공유해서 한쪽이 값을 바꾸면 다른쪽도 바뀐다는 이야기였음.
근데 여기서 중요한 개념이 하나 있음.
var a = {num: 1};
function change(val) {
val.num = 2;
console.log(val);
}
change(a); // {num: 2}
console.log(a); // {num: 2}
change()라는 함수를 통해 바깥에 있던 a도 {num: 2}로 바뀐다는 흔한 코드임.
var a = {num: 1};
function change(val) {
val = {num: 2};
console.log(val);
}
change(a); // {num: 2}
console.log(a); // {num: 1}
왜 여기서는 바깥에 있는 변수가 영향을 안받을까
방금 전 코드랑 달라진건 한줄밖에 없음.
val.num = 2
val = {num: 2}
val.num처럼 그 값을 직접 변경(mutate)한다면 원본값도 변경이 되어서 밖에 있는 변수도 바뀐 값을 가짐.
예) val.num = 2
val.push()
val = {num: 2}처럼 그 값을 변경/할당(reassignment)한다면 함수 내에 있는 변수는 아예 다른 ref값을 갖는 다른 변수가 되어버림.
예) val = {num: 2}
val = null, {}, 195 기타등등
밖에 있는 a = {num: 1} 고 ref가 123이라면,
안에 있는 a = {num: 2} 고 ref가 456인거임.
그렇기때문에 함수 바깥에서 a를 호출하면 123인 a가 나오는것임.
에이 바깥은 num: 1이고 안은 num: 2라서 당연히 다른거 아님??
var a = {num: 1};
var b = a;
function change(val) {
val = {num: 1};
console.log(val === b);
}
change(a); // false
console.log(a === b); // true
응 아냐
일부러 함수에서 값 똑같은걸로 다시 할당(reassignment)을 하고
a와 ref가 같은 b랑 대조해봄.
함수 안에서 false뜸.
var a = {num: 1};
var b = a;
a = {};
console.log(a); // {}
console.log(b); // {num: 1}
함수의 인자로 들어갈때 어쩌고저쩌고 했다고 함수탓이 아님.
위 코드만 봐도 함수따위 안써도 이런 증상이 나타남.
mutate vs reassignment 개념임.
그렇다면 이제 원시값을 보면
var c = 1;
function change() {
c = 2;
console.log(c);
};
change(); // 2
console.log(c) // 2
change()라는 함수를 통해 바깥에 있던 c도 값이 2로 바뀐다는 흔한 코드임.
var c = 1;
function change(val) {
val = 2;
console.log(val);
};
change(c); // 2
console.log(c) // 1
하지만 그런 원시값도 함수의 인자로 들어간다면 이야기가 달라짐.
인자로 들어가는순간 ref로 들어감.
설명했듯이 object는 애초에 ref로 들어가기때문에 mutate를 했냐, reassignment를 했냐에 따라 원본값이 차이남.
그러나 primitive는 애초에 a = 1 이런 할당 방식이기때문에 애초에 reassignment밖에 안됨.
바깥에 있는 c = 1은 ref 123인데
함수의 인자로 들어가서 값을 할당하는 순간 ref가 456인 또다른 c가 되어버림.
그 함수 안에서는 456의 c로써 나타나겠지만 함수 바깥에서는 123인 c가 지배하고 있어서 힘을 못씀.
'Javascript' 카테고리의 다른 글
🌟추천🌟😈함수 안과 밖에서 원시값은 어떻게 달라질까? (0) | 2021.01.18 |
---|---|
🌟추천🌟유용한 array (0) | 2021.01.16 |
array 메소드 기본 정리 (0) | 2020.12.07 |
😭원시값, 객체, undefined, false, 연산자... (0) | 2020.11.08 |
자바스크립트 : 배열에서 서로 값 바꾸고 싶을때 (0) | 2019.12.18 |