코어 자바스크립트를 읽고 스터디 세션에서 공유를 위해 정리한 글입니다.
↑ 데이터 타입의 종류
let a = 6; a = ‘a’;
와 같이 기본형에서 재할당이 가능하기에 값이 변할 수 있는데 어째서 immutable한지는 이후에 설명하겠다.식별자 사용
변할 수 있는 수
라는 수학용어 차용. 컴퓨터 용어에서는 변할 수 있는 무언가(variable이라는 형용사를 명사로 확장) 즉, 변할 수 있는 데이터
를 의미한다.변수를 식별하는 데 사용하는 이름, 즉 변수명
이다.var a;
변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 a로 한다.
가 된다.변경 가능한 데이터가 담길 수 있는 공간
이라는 설명이 적절하다.
↑ 변수 선언에 대한 메모리 영역의 변화(실제 메모리 구조보다는 추상화 시켜 표현)
var a; // 선언
a = 'abc'; // 할당
var a = 'abc'; // 변수 선언과 할당을 한 문장으로 표현
↑ 데이터 할당에 대한 메모리 영역의 변화
💡 데이터 변환의 경우(변수 재할당)
만약 변수 영역에 해당하는 단계에서 데이터를 직접적으로 저장할 경우 데이터의 길이가 변했을 때, 이전 데이터에 맞춰 확보된 공간을 변환된 데이터 크기에 맞춰 늘리거나 줄이는 작업 필요. → 이는 변환하고자 하는 메모리 공간 뒤의 데이터들을 다 뒤로 밀고 그 밀려난 새로운 주소를 식별자와 매핑해줘야 한다.
↑ 변수영역에 해당하는 영역에서 바로 데이터 변환이 이뤄지는 경우의 비효율성
💡 메모리 효율적 관리의 경우(같은 값을 가지는 여러 변수)
- 한 값을 가지는 여러 변수를 만드는 경우 실질적 데이터 저장을 위한 공간이 변수의 개수 * 데이터 크기 만큼의 공간 필요
- 데이터 영역으로 분리해서 저장 시, 1개의 데이터 크기만큼의 공간만 필요
↑ 데이터 영역을 분리하지 않았을 경우 메모리 공간 차원에서의 비효율성
❓ Q. const 상수는 변경 불가능하니 불변값이 아닌가요?
A. 결론
- 변수(variable) vs. 상수(const):
변수영역
에 해당하는 변수 공간에 다른 데이터를 재할당 불가한가 여부로 구분- 불변성(immutability):
데이터 영역
에 해당하는 변수 공간에 다른 데이터를 재할당 불가능한가 여부로 구분- 기본형 데이터인 Number, Boolean, String, Symbol, undefined, null은 불변값이다.(immutable)
var a = 'abc';
a = a + 'def'; // abc = 'abcdef';
var b = 5;
var c = 5;
b = 7;
→ 이 경우 사용되지 않는 데이터 공간인 5004 → ‘abc’만 가비지 컬렉터에 의해 제거되고 이 값만이 불변성을 가지지 않는다.
var obj1 = {
a: 1,
b: 'bbb'
};
obj1.a = 2
↑ 데이터 영역은 공유하나 obj1의 변수영역을 따로 가진다. 만약 obj1에 참조형 데이터가 프로퍼티로 들어오게 된다면 그 데이터만의 변수영역을 따로 가지게된다.
JS의 가비지 컬렉팅 방식
이렇게 참조 카운팅을 이용한 가비지 컬렉팅 알고리즘을 Reference-counting garbage collection 이라고 한다. 하지만 순환 참조의 경우 카운팅이 0이 되지 않기 때문에 지금은 사용하지 않는다고 한다. 지금은 Mark-and-sweep 알고리즘을 사용한다고 한다. 대략적으로 트리 순회하며 방문처리(mark)해 중복된 방문을 막고 연결된 객체들을 순회한 후 도달할 수 없는 (non-reachable) 객체를 메모리에서 해제.
var obj1 = {
prop1: 1,
prop2: 'bbb'
}
var obj2 = obj1;
var c = 1;
var d = c;
obj1.prop1 = 2;
// obj2.prop1도 2로 바뀜
d = 3;
// c는 1이고 d는 3으로 바뀜
기본형은 값을 복사하고 참조형은 주소값을 복사한다
고 설명하지만, 엄밀히 따지면 자바스크립트의 모든 데이터 타입은 변수에 할당하기 위해 주소값을 복사해야하기 때문에 참조형이라 할 수 있다.const copyObjectDeep = (target) => {
let result = {};
if (typeof target === 'object' && target !== null) {
for (let prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
const obj1 = {
a: 1,
b: 'lion',
c: {
a: 1,
b: 'lion'
}
}
const obj2 = copyObjectDeep(obj1);
obj1.a = 'otter'
console.log(obj1); // { a: 'otter', b: 'lion', c: { a: 1, b: 'lion' } }
console.log(obj2); // { a: 1, b: 'lion', c: { a: 1, b: 'lion' } }
const copyObjectDeepViaJSON = (target) => {
return JSON.parse(JSON.stringify(target));
}
값을 대입하지 않은 변수, 즉 데이터 영역에 메모리 주소를 지정하지 않은 식별자에 접근하려고 할 때
객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할 때
return 문이 없거나 호출되지 않는 함수의 실행 결과
var a;
console.log(a); // undefined
var obj = { a: 1 };
console.log(obj.b); // undefined
function func() { }
const c = func();
console.log(c);
var arr1 = [];
arr1.length = 3;
console.log(arr1); // [empty × 3]
var arr2 = new Array(3);
console.log(arr2); // [empty × 3]
var arr3 = [undefined, undefined, undefined];
console.log(arr3); // [undefined, undefined, undefined]
💡 사용자가 직접 할당한 undefined는 실존하는 데이터이다!
- 사용자 할당 undefined는 실존하는 데이터
- JS 엔진이 반환해주는 undefined는 문자 그대로 값이 없음을 의미한다.
→ 혼란을 유발할 수 있기 때문에, 직접 undefined를 할당하지 않고 JS 엔진이 반환하는 경우 즉, 우리의 통제 범위를 벗어난 경우에만 undefined가 할당될 수 있도록 하는 것으로 혼란을 피할 수 있다.
💡 그럼
비어있음
을 명시적으로 나타내기 위해서는 어떻게 할 것인가?
- null을 사용하면 되고 애초에 이런 용도로 만든 데이터 타입이다.
- 이런 규칙을 따르면
undefined가 값을 대입하지 않은 변수에 접근할 때 JS엔진이 반환하는 값
으로만 존재할 수 있다.
변수: 변경 가능한 데이터가 담길 수 있는 공간
식별자: 그 변수의 이름
변수 선언 → 메모리의 빈 공간(변수 영역)에 식별자 저장 → 자동으로 undefined 할당(var의 경우)
참조형 데이터를 불변값으로 사용하는 방법
없음을 나타내는 값