자바스크립트 엔진은 메모리에서 비어있는 공간을 확보하고, 그 공간의 이름을 설정한다.
var a; // 변할 수 있는 데이터를 만들고, 이 데이터의 식별자는 a로 한다.
별도의 메모리 공간을 확보해서 문자열 데이터를 저장하고, 그 주소를 식별자를 검색해서 데이터 값에 저장한다.
var a; // 변수 a 선언
a = 'abc'; // 변수 a에 데이터 할당
var a = 'abc'; // 변수 선언과 할당을 한 문장으로 표현
→ 효율적인 처리를 위해 변수와 데이터를 별도의 공간에 나누어 저장한다.
var a = 'abc'; // 변수 a에 문자열 'abc'를 할당
a = a + 'def'; // 새로운 문자열 'abcdef'를 만들어 그 주소를 변수 a에 저장
var b = 5; // 변수 b에 숫자 5를 할당
var c = 5; // 데이터 영역에서 5를 찾아서 그 주소를 재활용하여 변수 c에 저장
b = 7; // 기존에 저장했던 7을 찾아서 있으면 재활용하고, 없으면 새로 만들어서 b에 저장
'객체의 변수(프로퍼티) 영역'이 별도로 존재
var obj1 = {
a: 1,
b: 'bbb'
};
변수 영역은 변하지 않고, 기존 객체 내부의 값만 변경
var obj1 = {
a: 1,
b: 'bbb'
};
obj1.a = 2;
중첩 객체(nested object): 참조형 데이터의 프로퍼티에 다시 참조형 데이터를 할당
var obj1 = {
x: 3,
arr: [ 3, 4, 5 ]
};
→ 더 이상 자신의 주소를 참조하지 않는 경우 참조 카운트가 0이 되고, 해당하는 메모리 주소는 가비지 컬렉터의 수거 대상이 되어서 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때 마다 자동으로 수거된다.
기본형 데이터와 참조형 데이터의 변수 복사 과정은 동일하지만
데이터 할당 과정에서 이미 차이가 있기 때문에 변수 복사 이후의 동작에 큰 차이가 발생한다.
var a = 10;
var b = a;
var obj1 = { c: 10, d: 'ddd' };
var obj2 = obj1;
값으로 전달받은 객체에 변경을 가하더라도 원본 객체는 변하지 않아야 하는 경우에 불변 객체가 필요
// 객체의 가변성에 따른 문제점
var user = {
name: 'Rami',
gender: 'female'
};
var changeName = function (user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
};
var user2 = changeName(user, 'Jung');
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); // result: Jung Jung
console.log(user === user2); // result: true
changeName 함수가 새로운 객체를 반환하도록 수정
// 객체의 가변성에 따른 문제점의 해결 방법
var changeName = function (user, newName) {
return {
name: newName,
gender: user.gender
};
};
copyObject 함수를 통해 간단하게 객체를 복사하고 내용을 수정
// 얕은 복사(기본 정보를 복사해서 새로운 객체를 반환하는 함수)
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
};
얕은 복사(Shallow Copy)
깊은 복사(Deep Copy)
// 객체의 깊은 복사를 수행하는 범용 함수
var copyObjectDeep = function (target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
};
// JSON을 활용한 간단한 깊은 복사
var copyObjectViaJSON = function (target) {
return JSON.parse(JSON.stringify(target));
};
// (1) 값을 대입하지 않은 변수에 접근
var a;
console.log(a); // result: undefined
// (2) 존재하지 않는 프로퍼티에 접근
var obj = { a:1 };
console.log(obj.a); // result: 1
console.log(obj.b); // result: undefined
// (3) 반환 값이 없으면 undefined를 반환한 것으로 간주
var func = function() { };
var c = func();
console.log(c); // result: undefined
var n = null;
// typeof null이 object라는 자바스크립트 자체 버그 주의
console.log(typeof n); // result: object
// 동등 연산자(equality operator)로 비교할 경우 null과 undefined가 서로 같다고 판단
console.log(n == undefined); // result: true
console.log(n == null); // result: true
// 일치 연산자(identity operator)를 써야만 정확히 판별 가능
console.log(n === undefined); // result: false
console.log(n === null); // result: true
데이터 타입
- 기본형 → 불변값
- 참조형 → 가변값
변수: 변경 가능한 데이터가 담길 수 있는 공간
식별자: 그 변수의 이름
변수 선언 동작 원리
1. 메모리의 빈 공간에 식별자를 저장
2. 그 공간에 자동으로 undefined 할당
3. 변수에 데이터 할당시
3.1. (기본형 데이터인 경우)
3.1.1. 별도의 공간에 데이터를 저장
3.1.2. 그 공간의 주소를 변수의 값 영역에 할당
3.2. (참조형 데이터인 경우)
3.2.1. 참조형 데이터 내부 프로퍼티들을 위한 변수 영역을 별도로 확보해서 확보된 주소를 변수에 연결
3.2.2. 앞서 확보한 변수 영역에 각 프로퍼티의 식별자를 저장
3.2.3. 각 데이터를 별도의 공간에 저장해서 그 주소를 식별자들과 매칭
참조형 데이터를 불변값으로 사용 하는 방법
- 깊은 복사: 내부 프로퍼티들을 일일이 복사
- 라이브러리 사용
'없음'을 나타내는 값
- undefined: 어떤 변수에 값이 존재하지 않을 경우
- null: 사용자가 명시적으로 '없음'을 표현하기 위해 대입한 값