
👉 ‘코어 자바스크립트’의 ‘01 데이터 타입’을 읽으며 기억할 내용들과 새로 알게 된 내용을 정리하였습니다.
Number, String, Boolean, null, undefined, SymbolArray, Function, Date, RegExp, Map, WeakMap, Set, WeakSet// 가변한 데이터, 식별자는 a.
var a;
| 주소 | 1003 |
| 데이터 | 이름: a 값: undefined |
var a;
a = 'abc';
var a = 'abc'; // 변수 선언 및 할당 한 문장 표현
| 변수 영역 | 주소 | 1003 |
| 변수 영역 | 데이터 | 이름: a 값: @5004 |
| 데이터 영역 | 주소 | 5004 |
| 데이터 영역 | 데이터 | 'abc' |
불변값
var a = 'abc'; // 'abc'가 'abcdef'로 바뀌는 게 아니라 새로 'abcdef'를 만들어 저장.
a = a + 'def'; // 'abc'와 'abcdef'는 완전히 별개의 데이터.
var b = 5; // 5를 만들어 저장.
var c = 5; // b의 5를 재할당.
b = 7; // 5를 7로 바꾸는 게 아니라 기존의 7을 찾거나 새로 만들어서 저장.
가변값
var obj1 = {
a: 1,
b: 'bbb'
};
| 변수 | 주소 | 1002 | ||
| 영역 | 데이터 | 이름: obj1 값: @5001 |
||
| 데이터 | 주소 | 5001 | 5003 | 5004 |
| 영역 | 데이터 | @7103 ~ ? | 1 | ‘bbb’ |
| 객체 @5001의 | 주소 | 7103 | ||
| 변수 영역 | 데이터 | 이름: a 값: @5003 |
이름: b 값: @5004 |
객체의 변수(프로퍼티) 영역이 별도로 존재한다. var obj1 = {
a: 1,
b: 'bbb'
};
obj1.a = 2;| 변수 | 주소 | 1002 | |||
| 영역 | 데이터 | 이름: obj1 값: @5001 불변 |
|||
| 데이터 | 주소 | 5001 | 5003 | 5004 | 5005 |
| 영역 | 데이터 | @7103 ~ ? | 1 | ‘bbb’ | 2 |
| 객체 @5001의 | 주소 | 7103 | |||
| 변수 영역 | 데이터 | 이름: a 값: @5005 가변 |
이름: b 값: @5004 |
변수 복사 비교
✅ 원시 타입은 값 자체가 복사되므로 독립적
✅ 참조 타입은 주소를 복사하므로, 복사본을 변경하면 원본도 영향을 받음
✅ 객체를 독립적으로 복사하려면 얕은 복사 또는 깊은 복사 필요
✅ 얕은 복사는 1단계만 복사, 깊은 복사는 모든 중첩 객체까지 복사
💡 결론
✔ 원시 타입(number, string 등)은 값 복사
✔ 객체(object, array, function)는 참조 복사
✔ 불필요한 참조 공유를 방지하려면 깊은 복사를 고려해야 함! 🚀
불변 객체를 만드는 간단한 방법
왜 불변 객체가 필요한가?
값으로 전달받은 객체에 변경을 주더라도, 원본 객체는 변하지 않아야 하는 경우.
var user = {
name: "Kim",
gender: "female"
}
var changeName = function(user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
}
var user2 = changeName(user, 'Jung');
console.log(user.name, user2.name) // Jung Jung
위 예시처럼 user2 호출 시, 내부 프로퍼티만 변경함으로써 기존 user 객체를 동시에 변경(가변성)
user와 user2가 다른 값을 가질 수 있도록 하려면 아래와 같이 새로운 객체를 반환하도록 수정.
var user = {
name: "Kim",
gender: "female"
}
var changeName = function(user, newName) {
return {
name: newName,
gender: user.gender
}
}
var user2 = changeName(user, 'Jung');
console.log(user.name, user2.name) // Kim Jung
하지만, 변경된 코드의 경우 변경할 필요가 없는 기존 객체의 ‘gender’속성도 하드코딩으로 입력. 객체에 정보가 많을수록 비효율적인데, 프로퍼티 개수에 상관없이 모든 프로퍼티를 복사하는 함수를 만들 수 있음.
// 얕은 복사
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop]
}
}
물론 협업하는 모든 개발자들이 copyObject라는 얕은 복사를 사용하면 문제가 되지 않음. (= user 객체가 곧 불변 객체)
하지만, 그 규칙을 지키지 않을 수도 있으므로 아예 프로퍼티를 변경할 수 없게 제약을 거는게 더 안전.
얕은 복사와 깊은 복사
얕은 복사(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;
}
target이 객체인 경우에는 내부 프로퍼티를 순회하며 copyObjectDeep 함수를 재귀적으로 호출하고, 객체가 아닌 경우에는 target을 그대로 지정.
이 함수는 원본과 사본이 서로 완전히 다른 객체를 참조하게 하여 어느쪽의 프로퍼티를 변경하더라도 다른 쪽에 영향을 주지 않음.
undefined와 nullundefined와 null은 자바스크립트에서 모두 ‘없음'을 의미. 하지만 미세한 차이점이 존재.undefinedundefined를 반환.return 문이 없거나 호출되지 않는 함수의 실행 결과nullnull은 ‘비어있음'을 명시적으로 나타내고 싶을 때 사용.typeof null은 object라고 반환되는데, 이는 자바스크립트 자체 버그. 따라서 변수의 값이 null인지 확인하려면 일치 연산자로 확인 필요.undefined와 null을 구분하기 위해서는 동등 연산자 대신, 일치 연산자(===)를 사용.
var n = null;
console.log(typeof n); // object
console.log(n == undefined); // true
console.log(n == null); // true
console.log(n === undefined); // false
console.log(n === null); // true