bytrustu tech blog

[Javascript] 데이터 타입 본문

Javascript

[Javascript] 데이터 타입

bytrustu 2023. 1. 3. 01:50

 

Javascript의 데이터 타입으로는 기본형과 참조형으로 구분된다.

기본형은 불변성의 특징을 가지고 있고, 참조형은 가변적이라고 하는데 이것을 잘 이해하려면 메모리 영역에서 데이터 처리과정을 알아야 할 필요가 있다.

데이터 처리과정

기본형

 

1. 변수 영역에서 빈 공간 @1003을 확보한다.

2. 확보한 공간에 식별자를 a로 지정한다.

3. 데이터 영역에서 'abc' 문자열을 검색하고 없다면 빈 공간 @5004에 문자열 'abc'를 저장한다.

위와 같은 방법으로 변수 영역에 사용할 값을 데이터 영역에서 검색 후, 없다면 새로운 공간에 값을 저장하고 값에 해당 메모리주소를 반영한다.

 

변수 a에 새로운 값을 입력하면 어떨까?

새로운 값을 입력했을 경우에도 위와 같은 방법으로 변수 영역에서 해당 값을 검색 후, 없다면 새로운 공간에 값을 저장하여 메모리 주소를 반영하고, 검색했을 때 있을 경우 해당 메모리주소를 반영한다.

 

기본형 타입의 변수에 변수를 할당하면 어떨까?

// Step1
let a = 'hello';
let b = a;
console.log(a === b); // true

// Step2
b = 'world';
console.log(a === b); // false

Step1의 경우 변수 b의 변수 영역 공간에 a의 값 메모리주소가 할당된다.

Step2의 경우 변수 b에 새로운 값을 할당하기 때문에 데이터 영역에 해당 값이 없다면 빈 공간에 문자열 'world'를 저장하여 해당 메모리주소를 값으로 반영해 준다. 그래서 a === b의 값은 false이다.

 

이렇게 기본형의 경우에는 한번 생성된 변수의 공간은 불변하지 않도록 유지되고 값의 메모리주소만 변경되기 때문에 불변성이 띈다고 말할 수 있다.

 

 

참조형

 

1. 변수 영역에서 빈 공간 @1002를 확보한다.

2. 확보한 공간에 식별자를 obj로 지정한다.

3. 빈 공간 @5002에 객체에 포함되는 변수영역의 메모리주소 범위를 저장한다.

4. 지정된 범위에 빈 공간을 확보하고 식별자와 값을 지정한다. 값은 데이터 영역에서 검색 후 있으면 해당 메모리주소를 할당하고 없으면 새로운 공간에 값을 저장하여 해당 메모리 공간에 저장한다.

5. 변수 영역에 사용할 값을 데이터 영역에서 검색 후, 없다면 새로운 공간에 값을 저장하고 값에 해당 메모리주소를 반영한다.

 

변수 obj의 프로퍼트 a에 다른 값을 넣으면 어떻게 될까?

@1002 => @5002 => @7103의 순으로 obj.a 를 찾아간다. 그리고 새로 할당할 2의 값은 데이터 영역에 새로운 공간을 확보하고 2를 저장하여 해당 메모리주소를 @7103의 값에 반영한다.

 

기본형과 참조형의 데이터 영역이 어떻게 다를까?

기본형은 변수 영역의 값의 메모리주소가 값을 가지고 있지만, 참조형은 객체의 메모리주소 영역을(@7103~?) 가지고 있다.

참조형을 다른 변수에 할당하게 되면 할당받은 변수의 값에 메모리주소가 반영이 된다.

그래서 할당받은 변수에서 프로퍼티를 수정하게 되면 본래의 변수에도 해당 값으로 확인이 가능한 것이다.

// Step1
const obj = {
  a: 1,
  b: 'bb',
};
let obj2 = obj;
console.log(obj === obj2); // true

// Step2
obj2.a = 2;
console.log(obj === obj2); // true

// Step3
obj2 = {...obj};
console.log(obj === obj2); // false

Step1의 경우 변수 obj의 값 메모리주소를 할당받기 때문에 서로는 동일하다.

Step2의 경우 obj2.a 값을 변경하였더라도 obj와 같은 메모리주소 번지를 값으로 사용하고 있기 때문에 동일하다.

Step3의 경우 obj2에 obj 객체를 얕은 복사로 할당을 했기 때문에 새로운 공간에 해당 값들을 반영 후 메모리주소를 반영하기 때문에 서로 동일하지 않다.

 

불변 객체(Immutable object)를 만드는 방법

불변 객체는 프론트엔드 프레임워크, 디자인 패턴등 중요하게 사용되는 개념입니다.

참조형 데이터의 '가변'은 데이터 자체가 아닌 내부 프로퍼티를 변경할 때만 성립합니다.

데이터 자체를 변경하고자 하면 기본형 데이터와 마찬가지로 기존 데이터는 변하지 않습니다.

리액트에서는 불변성의 원칙에 따라 상태관리를 구현하고 있습니다.

이전 상태와 비교해 변경된 부분만 리렌더링해야 하기 때문에 이전 상태가 원본을 유지해야 합니다.

또한 state는 객체 형태이고 내부 속성값만 변경해서는 참조 값이 변경되지 않았기 때문에 리렌더링이 되지 않는 문제도 생깁니다.

 

 

얕은 복사(shallow copy)

 

얕은 복사는 바로 아래 단계의 값만 복사하는 방법입니다. 중첩된 객체에서 참조형 데이터가 저장된 프로퍼티를 복사할 때 그 주소값만 복사합니다.

const copyObject = (target) => {
  const result = {};
  for (const prop in target) {
    result[prop] = target[prop];
  }
  return result;
};

const user = {
  name: 'bytrustu',
  urls: {
    blog: 'https://bytrustu.tistory.com',
    github: 'https://github.com/bytrustu',
  }
};

// step1
const user2 = copyObject(user);
console.log(user === user2); // false

// step2
user2.urls.blog = 'https://';
console.log(user.urls.blog === user2.urls.blog); // true

Step1의 경우 user2에는 얕은 복사로 객체를 새로 할당받았기 때문에 서로 동일하지 않습니다.

Step2의 경우 user2.urls.blog 값을 변경을 했지만, 얕은 복사를 했기 때문에 내부 프로퍼티의 객체 값은 user와 메모리주소는 동일하게 가지고 있습니다. 그래서 user.urls.blog의 값도 'https://'로 동일하게 확인할 수 있습니다.

 

 

깊은 복사(deep copy)

 

깊은 복사는 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법입니다.

깊은 복사를 구현할때는 null의 경우 typeof의 결과가 object 임의 주의 해야 한다.

const copyObject = (target) => {
  const result = {};
  if(typeof target === 'object' target !== null) {
    for (const prop in target) {
      result[prop] = copyObject(target[prop]);
    }
  } else {
    result = target;
  }
  return result;
};

const user = {
  name: 'bytrustu',
  urls: {
    blog: 'https://bytrustu.tistory.com',
    github: 'https://github.com/bytrustu',
  }
};

// step1
const user2 = copyObject(user);
console.log(user === user2); // false

// step2
user2.urls.blog = 'https://';
console.log(user.urls.blog === user2.urls.blog); // false

간단한 방법으로는 JSON으로 변환 후 모든 내용을 복사하는 방법도 있다.

const copyObject = (target) => {
  return JSON.parse(JSON.stringify(target));
};

 

undefined와 null의 차이

Javascript 에서는 값이 없는 것을 표현할 때 undefined, null 두 가지가 있다.

데이터처리 과정에서 두 값이 어떻게 다른지 이해할 필요가 있다.

undefined는 값이 할당되지 않았을 때 자바스크립트 엔진이 자동으로 할당하는 값이고, null은 아무 값도 없다는 의미의 데이터 형이다.

 

undefined

 

1. 값을 대입하지 않은 변수, 즉 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근할 때

2. 객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할 때

3. return 문이 없거나 호출되지 않는 함수의 실행 결과

 


이렇게 Javasciprt의 데이터 타입에 대해서 알아보았다.

기본형이 왜 불변성의 규칙을 가지고 있는지, 참조형의 가변적으로 변경되는 메모리 구조에 대해서 정확히 알 수 있었다.

Comments