메모리는 byte 단위로 구분한다
let str;
str = 'test!'
라면 변수 영역에 str 과 데이터 영역의 주소를 저장한다
이후 데이터 영역에 데이터를 따로 저장하여 관리한다
=> 여기서 변수 영역에 바로 값을 대입하지 않고 따로 저장하여 관리하는 이유
1. 자유로운 데이터 변환
변수 영역에 데이터를 직접 저장하고 데이터를 변경하여 길이가 달라지면 옆에 있는 변수 영역을 전부 뒤로 미뤄야 하는 작업이 필요하다
따라서 데이터 영역을 따로 관리하는 것이 효율적이다
똑같은 데이터를 같은 변수에 저장한다면 각각의 변수를 길게 저장하는 것 보다 데이터 영역의 주소값만 각각의 변수에 저장하는 것이 데이터 측면에서 효율적이기 때문이다
변수 vs 상수
변수 -> 변수 영역 메모리를 변경할 수 있어야 한다
상수 -> 변수 영역 메모리를 변경할 수 없음
불변하다 vs 불변하지 않다
불변하다 -> 데이터 영역의 메모리를 변경할 수 없다
불변하지 않다 -> 데이터 영역의 메모리를 변경할 수 있다
abc가 데이터 영역 @5002 번으로 들어갔다고 했을 때,
abcdef 가 되기 위해서 @5002 번에 데이터가 추가되는 것이 아닌,
@5003 번에 별도로 abcdef 가 생기고 변수 a 의 데이터 주소가 @5003 으로 바뀐다
즉, @5002 의 데이터는 '불변하다'
이후 필요가 없어진 @5002 는 JS 의 Garbage collector 에 의해서 수거된다
let obj1 = {
a :1,
b: 'bbb'
}
obj 라는 변수를 변수영역에 저장하고
데이터 영역에 1 과 'bbb' 를 저장 후
obj 의 별도 영역에 a/@5001(데이터 영역) 과 b/@5002 를 저장한다
여기서 obj1.a = 2 라는 값을 재할당하면
데이터 영역 @5003 에 2 라는 값을 저장하고
obj 영역이 a/@5003 으로 바꿔서 저장한다
=> 여기서 변수 영역이 아닌 obj 영역은 변경이 되었다
obj 영역은 데이터 영역으로 분류되기 때문에 ~참조형 데이터는 불변하지 않다~
var obj = {
x: 3,
arr: [3, 4, 5],
}
->참조 카운트란 객체를 참조하는 변수나 다른 객체의 수를 나타내고
0일 경우 garbage collector 에게 제거된다
// STEP01. 쭉 선언을 먼저 해볼께요.
var a = 10; //기본형
var obj1 = { c: 10, d: 'ddd' }; //참조형
// STEP02. 복사를 수행해볼께요.
var b = a; //기본형
var obj2 = obj1; //참조형
복사까지 수행 완료
여기서
b = 15;
obj2.c = 20;
이렇게 요소를 바꿔주게 되면
a !== b; // 기본형은 당연히 다른 결과가 나오지만
obj1 === obj2 // obj2 를 변경했는데 (7103은 obj1 도 참조하기 때문에)
obj1 도 따라서 변경된다
여기서
let obj3 = {
c:20,
d:'ddd'
}
를 선언하게 되면
obj3을 위한 별도 obj 데이터인 7105, 7106이 생겨 다른 데이터를 바라보게 된다
따라서 obj2 !== obj3; 이 되는 것이다
객체의 가변성으로 인해 객체를 복사할 경우 기존의 객체와 같이 참조를 하는 문제가 있었다
그래서 얕은 복사를 통해 매번 새로운 객체를 생성하여 onj1 !== onj2 를 보장받을 수 있다
var user = {
name: 'wonjang',
gender: 'male',
};
var changeName = function (user, newName) {
return {
name: newName,
gender: user.gender,
};
};
user 객체를 복사하기 위래 changeName 이라는 function 을 만들어서 복사하면 매번 새로운 객체를 생성하기 때문에 기존의 객체와는 다른 참조를 가진 객체를 생성할 수 있다
하지만 이 방법은 객체의 각각 key를 직접 입력해주어야 하기에 작업량이 늘어날 수 있다
따라서
var copyObject = function (target) {
var result = {};
// for ~ in 구문을 이용하여, 객체의 모든 프로퍼티에 접근할 수 있습니다.
// 하드코딩을 하지 않아도 괜찮아요.
// 이 copyObject로 복사를 한 다음, 복사를 완료한 객체의 프로퍼티를 변경하면
// 되겠죠!?
for (var prop in target) {
result[prop] = target[prop];
}
return result;
}
for ~ in 구문을 활용해 객체의 모든 프로퍼티에 접근하여 복사할 수 있다
하지만 이 방법에도 문제가 있는데 ~중첩된 객체에 대해 완벽한 복사를 할 수 없다는 점이다~
객체 안 객체에 대해서는 주소를 복사해오는 문제가 생기게 된다
( 1depth 만 복사해서 가져오기 떄문에 )
재귀적 수행( re+cursive ) => 1depth 이상으로 깊은 depth 까지 다 반복적으로 수행하게 되는 방법이다
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[pop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
copyObjectDeep 이라는 function 을 돌리게 되면 자기 자신을 불러와서
객체이면서 비어있지 않은 경우에 복사를 실행하게 되는 코드이다
모든 요소 하나하나의 불변성을 다 유지할 수 있게 해준다
데이터 타입은 두가지로 나뉜다
1. 기본형
2. 참조형
기본형
number
string
boolean
null
undefined
symbol
참조형
참조형은 기본적으로 객체다
array
function
date
두 타입을 구분하는 기준
%주의
let test = 3
여기서 test -> 식별자
3 -> 변수
이다
개발자가 직접 적용해주는 경우는 거의 없고
JS 엔진이 '값이 있어야 할 것 같은데 왜 없지??' 할 때 자동으로 부여한다
개발자가 '이건 없는 값이야' 라고 명시해줄 때 사용된다 ( undefined 는 명시로 사용하지 않는다 )
typeof null == object
( JS 버그이다)
null == undefined // true
null == null // true
n === undefiend // false
n === null // true