→ 일반적으로 불변값
→ 일반적으로 가변값
참조 카운터가 0인 경우 GC에 의해 사라질 예정
(1) 객체의 프로퍼티 변경
var a = 10;
var b = a;
var obj1 = { c: 10, d: 'ddd'};
var obj2 = obj1;
b = 15; // a != b
obj2.c = 20; // obj1 === obj2
(2) 객체 자체를 변경
var a = 10;
var b = a;
var obj1 = { c: 10, d: 'ddd'};
var obj2 = obj1;
b = 15;
obj2 = { c: 20, d: 'ddd' };
(1) 변경 전 - 가변성에 따른 문제점
var user = {
name: 'Jimi',
gender: 'male'
};
var changeName = function (user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
}
var user2 = changeName(user, 'Jung');
if (user !== useer2) {
console.log ('유저 정보가 변경되었습니다');
}
console.log(user.name, user2.name); // Jung Jung
console.log(user === user2); // true
(2) 변경 후 - 기존 정보를 복사해서 새로운 객체를 반환하는 함수 (얕은 복사)
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user = {
name: 'Jimi',
gender: 'male'
};
var user2 = copyObject(user);
user2.name = 'Jung';
if (user !== useer2) {
console.log ('유저 정보가 변경되었습니다');
}
console.log(user.name, user2.name); // Jimi Jung
console.log(user === user2); // false
→ copyObject 함수를 사용하기로 합의하고 규칙을 지킨다는 전제 하에 user 객체는 불변 객체
얕은 복사
깊은 복사
(1) 객체의 깊은 복사를 수행하는 범용 함수
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;
}
→ 원본과 사본이 서로 완전 다른 객체를 참조하게 되어 어느 쪽 프로퍼티를 변경하더라도 영향을 주지 않음
(2) JSON을 활용한 간단한 깊은 복사
var copyObjectViaJSON = function (target) { //
return JSON.parse(JSON.stringify(target));
};
var obj = {
a: 1,
b: {
c: null,
d: [1, 2],
func1: function() { console.log(3); }
},
func2: function() { console.log(4));
};
var obj2 = copyObjectViaJSON(obj);
obj2.a = 3;
obj2.b.c = 4;
obj.b.d[1] = 3;
console.log(obj); // { a: 1, b: {c: null, d: [1,3], func1: f()}, func2: f() }
console.log(obj2); // { a: 3, b: {c: 4, d: [1, 2] } }
사용자가 명시적으로 지정할 수도 있지만 ‘값이 존재하지 않을 때’ 자바스크립트 엔진이 자동으로 부여하는 경우도 있음
자바스크립트 엔진이 부여하는 경우
(1) 값을 대입하지 않은 변수에 접근할 때
(2) 객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할 때
(3) return 문이 없거나 호출되지 않는 함수의 실행 결과
→ (1)에서 값을 대입하지 않은 배열의 경우는 empty가 출력됨.
배열은 객체이기 때문에 값이 지정되지 않은(존재하지 않는) 프로퍼티에 대해선 순회할 수 없음
❗ ES6의 let, const에 대해서는 undefined를 할당하지 않은 채로 초기화를 마치며, 이후 실제 변수가 평가되기 전까지는 해당 변수에 접근할 수 없음
- == 동등 연산자로 비교할 경우 null, undefined가 같다고 판단함
- typeof null이 object라는 버그가 있음
→ === 일치 연산자를 써야만 정확히 판별