와.... 이번 강의 진짜 역대급으로 어려웠다... 강의 하나를 거의 하루 종일 붙들고 되감기 되감기 무한루프해서 들었는데도 무슨 말인지 도저히 이해하기가 어려웠다.... 한 10번씩 듣고 나니까 어렴풋이 이해는 하겠는데 머릿속에 내용이 깔끔히 정리되지 않고 안개 낀 날씨마냥 흐릿하기만 하고 그러다보니 졸음이 밀려오기까지 했다.
데이터 타입은 1. 값의 저장방식과, 2. 불변성 여부에 따라 크게 기본형과 참조형으로 구분한다.
비트 bit:컴퓨터가 이해할 수 있는 가장 작은 단위로, 0과 1을 갖고 있는 작은 조각
바이트 byte: 8개의 비트로 만들어진 새로운 단위
메모리: byte 단위로 구성된다. 모든 데이터는 byte 단위의 식별자인 메모리 주소값을 통해서 서로 구분된다. 가령 64bit의 정수는 8byte로 분할하여 메모리에서 8개의 연속된 byte에 저장된다. 자바스크립트는 정수를 8바이트로 저장하여 메모리를 관리하며, 개발자가 메모리의 크기까지 고려할 필요가 없다. (JAVA, C언어는 다르다)
식별자와 변수:
아래 코드에서 testValue는 식별자이자 변수명이고, 3은 변수이자 데이터이다.
var testValue = 3
/** 선언과 할당을 풀어 쓴 방식**/
var str;
str = '안녕하세요";
/** 선언과 할당을 붙여 쓴 방식**/
var str = '안녕하세요";
변수를 선언할 때 값을 바로 변수 영역에 대입하지 않고, 새로 만든 공간(데이터 영역)에 저장하여 그 주솟값을 불러오는 식으로 하는데, 그 이유는 다음과 같다.
변수 vs 상수 - 변수 영역
변수: 변수 영역 메모리를 변경할 수 있음
상수: 변수 영역 메모리를 변경할 수 없음
불변하다 vs 불변하지 않다 - 데이터 영역
불변하다: 데이터 영역 메모리를 변경할 수 없음
불변하지 않다: 데이터 영역 메모리를 변경할 수 있음
불변값과 불변성(기본형 데이터):
데이터를 변경할 때 기존에 저장된 데이터를 변경하는 것이 아니라, 새로운 데이터를 새로운 공간에 저장하여 그 새로운 주소를 불러온다. 기존 데이터 영역 자체가 변경되는 것이 아니기 때문에 '불변하다'고 표현한다.
var aaa = '안녕'
aaa = '안녕하세요'
// '안녕' 값이 '안녕하세요'로 수정된 것이 아니라,
// 새로운 공간에 '안녕하세요'를 저장하여 새로운 주소를 불러오는 것
// ---> 변수 aaa는 불변하다.
// '안녕'이 저장되어 있는 공간은 더 이상 사용되지 않기 때문에
// JavaScript 가비지컬렉터의 수거 대상이 된다.
// obj1을 위한 별도 공간이 필요하다
var obj1 = {
a: 1,
b: 'bbb',
};
// 데이터 변경
obj1.a = 2;
// 배열을 포함하는 중첩 객체
var obj = {
x: 3,
arr: [3, 4, 5],
}
자바스크립트는 효율적으로 메모리를 관리하기 위해 자료형에 따라 복사를 다른 방식으로 진행한다. 기본형 데이터는 용량 예측이 쉽고 단순하기 때문에 깊은 복사를 하고, 참조형 데이터의 경우는 복잡한 객체를 다루기 때문에 얕은 복사가 이루어진다.
요약하면, 기본형 변수 복사의 결과는 서로 다른 값이고, 참조형 변수 복사의 결과는 같은 값이다. 따라서 가변하는 참조형 변수를 복사하면 같은 주소를 불러오는 값들이 동시에 변경되는 사태가 발생한다. 이 때는 객체의 프로퍼티에 접근해서 값을 변경하는 것이 아니라, 객체 자체를 변경하면 된다.
(1) Object.assign()
const coffee = {
name: '아메리카노',
price: 3000,
}
const newCoffee = Object.assign({}, coffee);
newCoffee.name = '카페라떼';
console.log(coffee.name); // 아메리카노
console.log(newCoffee.name); // 카페라떼
(2) spread operator (배열도 가능)
const coffee = {
name: '아메리카노',
price: 3000,
}
const newCoffee = { ...coffee };
newCoffee.name = '카페라떼';
console.log(coffee.name); // 아메리카노
console.log(newCoffee.name); // 카페라떼
(3) 배열.slice()
let array1 = [1, "안녕", true, 3.14];
let array2 = array1.slice();
array2[0] = 100;
console.log(array1[0]); // 1
console.log(array2[0]); // 100
(4) for - in 활용해서 새로운 객체 생성하기
var user = {
name: "김민지",
age: 20,
}
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user2 = copyObject (user);
user2.name = "신지유";
console.log(user.name, user2.name); // 김민지 신지유
함수나 알고리즘이 자기 자신을 호출하여 반복적으로 실행되는 것. 객체의 프로퍼티 중, 기본형 데이터는 그대로 복사하고, 참조형 데이터는 다시 그 내부의 프로퍼티를 복사하는 방법 (완전히 다른 객체를 반환)
var user = {
name: "김민지",
age: 20,
}
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
result[pop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
undefined:
(1) 변수에 값이 지정되지 않은 경우(데이터 영역의 메모리 주소를 지정하지 않은 식별자)
(2) .이나 []로 접근하려 할 때 해당 데이터가 존재하지 않는 경우
(3) return문이 없거나 호출되지 않는 함수의 실행 결과
null: '없다'를 명시적으로 표현
(typeof null이 object인 것은 javascript 자체 버그)