코어 자바스크립트 https://book.naver.com/bookdb/book_detail.nhn?bid=15433261 내용을 정리한 내용

데이터 타입의 종류

  • 자바스크립트의 데이터 타입에는 크게 두가지가 있다.
  • 기본형(primitive type)과 참조형(reference type)이다.
    • 기본형에는 숫자,문자열,불리언,null,undefined등이 있다
    • 참조형에는 객체가 있고, 배열,함수,날짜,정규표현식,Map,WeakMap,Set,WeakSet등이 객체의 하위에 포함
  • 기본형은 값이 담긴 주소값을 바로 복제하는 반면 참조형은 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제한다.

메모리와 데이터

컴퓨터의 메모리

컴퓨터는 모든 데이터를 0과 1로 바꿔서 기억을 한다. 0또는 1을 표현할 수 있는 하나의 메모리 조각을 bit(비트)라고 표현한다. 이때, 메모리는 매우 많은 비트들로 구성된다. 각 비트는 고유한 식별자를 통해 위치를 확인할 수 있다.

하지만, 0과 1만 표현할 수 있는 비트 단위로 위치를 확인하는 것은 매우 비효율적이다. 또한, 매우 많은 비트를 한 단위로 묶으면 검색 시간이 오래걸리고, 낭비되는 비트가 생기게 된다. 적절한 공간을 묶어 놓을 필요성이 생기고 이런 고민의 결과로 Byte(바이트) 단위가 생기게 되었다.

1Byte는 8bit로 구성되어 있다. 1bit마다 0/1로 표현할 수 있으므로 1Byte는 256개의 값을 표현할 수 있다.
또한, Byte는 시작하는 비트의 식별자(메모리 주소값)로 위치를 파악할 수 있다.

자바스크립트의 메모리

C/C++, 자바 등의 정적 타입 언어는 메모리 낭비를 줄이기 위해 데이터 타입별로 메모리 영역을 2바이트,4바이트 등으로 정해놓았다. 하지만, 자바스크립트는 상대적으로 메모리 관리에 대한 압박에서 자유로워졌다. (숫자의 경우 정수형, 부동소수형인지 구분하지 않고 64비트를(8byte)를 부여)

변수 선언과 데이터 할당

var a;

자바스크립트로 표현한 위의 표현을 풀어서 설명하면 "변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 a로 한다." 가 된다. 사용자가 변수를 선언하면 컴퓨터는 메모리에 비어있는 공간 하나를 확보한다. 해당 공간의 이름(식별자)를 a라고 지정하면서 "변수 선언"을 하게 된다.

image.png

만약, 위에서 선언된 변수에 데이터를 할당하면 메모리에서는 어떤 일이 발생할까? 1003주소의 메모리 값에 데이터를 직접 넣지 않고, 데이터를 저장하기 위한 별도의 메모리 공간을 새로 확보하고 데이터를 저장한다. 그리고 그 곳의 주소값을 1003번지 값에 저장시켜서 "주소값을 참조"하도록 한다.

직접 값을 저장하지 않고, 참조하는 이유

  • 데이터 변환을 자유롭게 할 수 있도록 하고 메모리 관리를 효율적으로 하기 위해서 위의 과정을 거친다.
  • 자바스크립트 문자열은 특별히 정해진 규격 없이 메모리에 올라가게된다 (메모리 용량이 가변적으로 할당). 만약, 값을 직접 1003번지에 올리면, 데이터의 수정 및 삭제작업이 비효율적 이다.
    • 확보된 공간을 변환된 데이터의 크기에 맞게 재할당하는 연산이 필요
      • 예) abc라는 문자열을 abbbc라는문자열로 수정한다면 ?
        • 'abc'에서 b의 뒷부분에 'bb'가 추가 되었으므로, 전체 메모리 공간을 늘려주고 c라는 문자열을 제일 뒤로 이동시켜야 한다.
          • 수정,삭제의 작업이 필요하다면, 새로운 메모리 공간을 확보하고 그 곳에 데이터를 새롭게 할당하고 그 주소값을 변수값에 mapping시킨다. 마지막으로 기존에 참조하고 있던 데이터는 garbage collector에 의해서 메모리에서 정리가 된다.

image.png

image.png

기본형 데이터와 참조형 데이터

기본형 데이터

  • 변수와 상수를 구분 하는 성질은 '변경 가능성' 이다. 변경 가능현 변수, 바꿀 수 없으면 상수
    • 변수와 상수를 구분할때 변경이 가능하다는 말은 변수영역 메모리의 변경유무
    • 불변성 여부를 구분할때의 대상은 데이터 영역 메모리의 변경유무
  • 기본형 데이터는 모두 불변값

불변성

한 번 만들어진 값은 가비지 컬렝팅 당하지 않는 한 영원히 변하지 않는다.

let a = 5;
let b = 5;
b = 7;

위의 코드에서 b를 7로 재할당하면, 메모리에 7을 담기위해 새로운 공간을 확보하고 기존의 주소값을 새로 생성한 주소로 변경시킨다. 즉, 5와 7이라는 데이터 자체는 변경할 수 없다.

참조형 데이터

  • 참조형 데이터는 가변값인 경우가 많지만, 설정에 따라 불변하게도 만들 수 있다.
let obj1 = {
    a : 1
}

기본형 데이터와는 다르게, 여러개의 프로퍼티로 이뤄진 데이터 그륩인 것을 확인하고, 내부의 프로퍼티들을 저장하기 위한 별도의 변수영역을 마련하고, 그영역의 주소를 5004에 저장한다.+
image.png

불변 객체 (Immutable Object)

참조형 데이터의 가변 성질은 데이터 자체가 아닌 내부 프로퍼티를 변경할 때만 성립한다. 데이터 자체를 변경하고자 하면 기본형 데이터와 마찬가지로 기존 데이터는 변하지 않는다. 내부 프로퍼티를 변경할 필요가 있을 때 마다 매번 새로운 객체를 만들어 재할당 하기로 규칙을 정하면 객체 불변성을 확보할 수 있다.

가변 객체

var user = {
    name : "홍길동",
    gender : "남"
}

var chagneName = function (user,newName) {
    var newUser = user;
      newUser.name = newName;
      return newUser;
}

var user2 = changeName(user,'임꺽정');

console.log(user.nanme,user2.name) // 임꺽정 임꺽정

불변 객체

var user = {
    name : "홍길동",
    gender : "남"
}

var chagneName = function (user,newName) {
    return {
        name : newName,
        gender: user.gender
    }
}

var user2 = changeName(user,'임꺽정');

console.log(user.nanme,user2.name) // 홍길동 임꺽정

얕은 복사와 깊은 복사

얕은 복사

  • 바로 아래 단계의 값만 복사하는 방법

깊은 복사

  • 내부의 모든 값들을 하나하나 찾아서 복사하는 방법
  • 객체 프로퍼티내부에 객체일 경우 재귀호출을 통해서 다시 한번 복사를 수행한다.
  • 객체가 아닐경우에는 target을 그대로 복사한다
  • getter/setter를 복사하는 방법은 Object.getOwnPropertyDescriptor, Object.getOwnPropertyDescriptors외에는 존재하지 않는다.

var copyObjectDeep = function(target) {
    var result = {};
  if(typeof target === 'objecgt' && target !== null) {
      for(var prop in target) {
        result[prop] = copyObjectDeep(target[prop]);
    }
  }
  else {
      result = target;
  }
  return result;
}

객체를 string으로 변환하고, 다시 parse하면서 깊은 복사를 할 수 있다.


var copyObjectViaJson = function(target) {
    return JSON.parse(JSON.stringfy(target))'
};

undefined 와 null

  • undefined는 사용자가 명시적으로 지정할 수도 있지만, 값이 존재하지 않을때 자바스크립트 엔진이 자동으로 부여하는 경우도 있다.
  • 사용자가 어떤 값을 지정할 거이라고 예상하는 상황임에도 실제로는 그렇게 하지 않았을때 undefined를 반환
    • 값을 대입하지 않은 변수, 즉 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근
    • 객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할때
    • return문이 없거나 호출되지 않는 함수의 실행결과
  • 사용자가 직접 undefined를 할당하지 않으면, 자바스크립트 엔진만이 undefined를 할당하므로 에러처리가 유용하다.
    • 사용자가 undefined를 할당하는 행위는, 값으로써 어딘가에 할당된 undefined는 실존해는 데이터
    • 엔진이 반환하는 undefined는 문자 그대로 값이 없음을 나타낸다.
    • 비어있음을 표현하고 싶으면 null을 사용
      • null의 type은 object(자바스크립트 버그)
      • null == undefined (true) 동등연산자
      • null === undefined (false) 일치 연산자

var a;
console.log(a) // undefined

var obj = {a: 1};
console.log(obj.b) // undefind
console.log(b) //error

var func = function() {};
var c = func();
console.log(c) // undefined;