TIL.52 Core J.S - 1 데이터 타입

Haiin·2021년 2월 15일
0

CoreJS

목록 보기
1/7
post-thumbnail

출저

  • 코어자바스크립트 - 정재남


데이터 타입 종류

- 기본형 (Primitive type)

숫자, 문자열, 불리언, null, undefined 등

- 참조형 (Reference type)

객체, 배열, 함수, 날짜, 정규표현식 등 (객체안에 포함된다고 봐도 된다.)



변수 선언과 데이터 할당

변수를 선언하고 데이터를 할당하는 일은 변수 영역, 데이터 영역에 값을 저장하고 그 주소를 할당하며 이루어진다.
1. 변수 영역 에서 빈 공간을 확보하고 할당된 이름(식별자)를 저장한다.
2. 데이터 영역 에서 값에 해당하는 정보를 찾고 없으면 빈 공간에 데이터를 저장한다.
3. 변수 영역에 해당 식별자를 찾아서 앞서 저장한 데이터의 주소를 값에 저장한다.

위와 같은 시스템은 데이터 변환을 자유롭게 할 수 있게 함과 동시에 메모리를 더욱 효율적으로 관리하기 위한 고민의 결과 이다.



불변값

변수 variable상수 constant 를 구분하는 성질은 변수 영역 메모리 이다. 한 번 데이터 할당이 이뤄진 변수 공간에 다른 데이터를 재할당할 수 있는지 여부 인 것이다.

반면,

불변성 여부는 변경가능성의 대상이 데이터 영역 메모리 이다. 앞서 알아본 기본형 데이터는 모두 불변값이다.

let a = "abc"
// a 변수에 "abc"를 할당했으니, 
// 1. a 라는 식별자를 변수 영역 메모리에 저장하고 
// 2. "abc" 라는 데이터를 데이터 영역 메모리에 할당하여 그 주소를 
// 3. 변수 영역 메모리의 값에 저장한다.

위와 같이 데이터 영역 메모리에 저장된 주소를 값에 저장하기 때문에 변수 a 에 다른 값을 넣어줘 바꿔준다고 해도 위의 2, 3번 과정을 새롭게 반복하기 때문에 값을 변경한다 (변한다) 라고 할 수 없다. 한 번 만들어진 값은 영원히 변하지 않는다. 이것이 불변값의 성질이다.



가변값

참조형 데이터 는 데이터를 저장할 때 객체의 변수(프로퍼티)영역 이 별도로 존재하는데 이는 변수 영역, 데이터 영역, 객체의 변수 영역 으로 나눠져서 데이터를 저장한다.

객체의 변수 영역변수 영역과 같이 이름(식별자) 을 저장하는데 여기에서 은 일반 변수 영역과 같이 데이터 영역의 주소를 저장한다.

let obj = {
  a: 1,
  b: "bbb"
}
// 1. obj라는 이름으로 변수 영역에 할당하고 
// 2. 값은 데이터 영역에 저장하는데 객체모양이기 때문에
// 3. 객체의 변수 영역에 이름:a 값:@5005(데이터 영역의 주소), 
// 이름:b 값:@5006 와 같은 형식으로 먼저 저장이 된다.
// 4. 위 3번의 주소2개를 변수 영역의 값 에 저장한다.
obj.a = 2
// 위는 변수 영역의 obj라는 식별자를 가진 값을 바로 바꾸는 것이 아니라 
// 그 값이 가르키고 있는 주소로 가서 그 데이터가 가르키고 있는 객체의 변수 영역의
// 값을 바꾸기 때문에 정작 변수 영역의 obj 의 값 @5005 는 그대로 이고
// 그것이 뜻하고 있는 실제 데이터가 바뀐다.

위의 이유로 인해 참조형 데이터는 가변값이라고 한다.

사실 기본형, 참조형 모두 주솟값을 참조한다.
여기서 차이점은

기본형은 주솟값을 복사하는 과정이 한 번만 이뤄지고, 참조형은 한 단계를 더 거치게 된다는 차이가 있다.

하지만, 객체 자체를 복사하면 새로운 객체 데이터를 만들기 때문에 위의 가변값이라고 설명할 때는 그 내부 프로퍼티를 변경할 때만 성립한다.



가변성의 불편함

위와 같이 객체가 가변성이 있다면 어떤것이 불편할까?

let userH = {
  name: "haiin",
  gender: "female"
}

const changeName = function (user, newName) {
  let newUser = user
  newUser.name = newName
  return newUser
}

let aa = changeName(userH, "kim")
console.log(aa) //{ name: 'kim', gender: 'female' }
console.log(userH) // { name: 'kim', gender: 'female' }

위의 코드에서 보다시피 객체 userH 를 직접적으로 바꾼적도 없는데 값이 바뀌어 버리는 결과가 나타난다.
다시 복습하자면, userH 와 aa 의 값이 가리키는 객체 데이터 주소가 같은데 여기서 객체 데이터 안에 있는 값의 데이터 값이 바뀌면서 결과적으로 주소는 이전과 같지만 값은 바뀌는 결과가 나타났기 때문이다.

이는 예상치 못한 버그나 원하지 않는 결과를 나을 수 있기 때문에 원본은 바뀌지 않는 불변성을 유지할 필요가 있다.



불변 객체 만드는 방법

  1. 위에서 잠깐 언급했던 객체 전체를 복사하면 새로운 객체 데이터가 만들어지기 때문에 새로운 불변 객체를 만들 수 있다.
    하지만, 데이터가 많아지게 되면 모두 하드코딩해야하는 불편함이 있다.

얕은 복사와 깊은 복사

얕은 복사 shallow copy 는 바로 아래 단계의 값만 복사하는 방법,
깊은 복사 deep copy 는 내부 모든 값들을 하나하나 찾아서 전부 복사하는 방법

  1. 중첩이 많이 된 객체는 결국에 깊은 복사를 하기에 어려운 점이 있으므로 immutable.js, baobab.js등의 라이브러리를 이용하거나 JSON.parse(JSON.stringify()) 를 이용하여 간단하게 깊은 복사를 할 수 있다.

  2. 이외에도 라이브러리(lodash, ramda)를 사용하는 방법도 있다.



undefined, null

데이터 타입에서 "없음"을 나타내는 값은 두가지가 있는데

undefined 는 어떤 변수에 값이 존재하지 않을 경우를 의미하고
null은 사용자가 명시적으로 "없음"을 표현하기 위해 대입한 값이다.

기억해야 할 점은
undefined 는 비어있는 요소가 아니다. 비어있는 요소는 메서드를 사용했을 때 어떤 결과도 출력하지 않고 건너뛴다. 하지만 undefined 를 만났을때는 건너뛰지 않고, NaN 이나 undefined 를 반환하는 것을 보아 비어있는 요소와는 다르다.
하지만, 데이터를 할당하는 측면에서 봤을때는 값에 undefined를 할당한 것 이 아니라

정확히는 아무것도 할당하지 않고 끝나며, 이후 변수 a 에 접근하고자 할 때 비로소 undefined 를 반환하는 것이 맞습니다.

null 은 typeof null 이 object 이다. 비어있는 객체를 표현하려고 할때 undefined 보다 null 을 사용할 것을 추천하지만 null 의 type 이 object 라는 것을 기억하고 코드를 작성해야 한다.

0개의 댓글