• [JS] 코어자바스크립트 - 01 데이터 타입

    2024. 10. 14.

    by. 지은이: 김지은

    728x90

     

    01. 데이터 타입의 종류

    타입 종류 설명
    기본형(Primitive) - 값 그 자체를 저장하는 타입
    - 변경 불가능 하여 변수에 값을 저장하고, 변수간의 값 비교나 복사값이 그대로 복사
    (Number, String, Boolean, Undefined, Null, Symbol, BigInt)
    참조형(Reference) - 값이 아닌 저장된 위치(주소)를 저장
    - 변경 불가능하여 한 변수에서 객체의 값을 변경하면,그 객체를 참조하는 다른 변수에도 변경사항이 보이게 됨
    (Object, Array, Function, Date, RegExp)

     

    02. 데이터 타입에 관한 배경지식

    1) 비트: 컴퓨터가 데이터를 처리하는 가장 기본적인 단위로, 컴퓨터는 모든 데이터를 0과 1비트 단위로 저장

    하지만, 비트만 사용하면 많은 데이터를 처리하기 어렵기때문에 비트를 모아 바이트 단위로 묶음

    • 비트: 0또는 1만 저장할 수 있는 기본 단위
    • 바이트: 8개의 비트가 모인 단위 (1바이트는 0부터 255까지를 표현)

    2) 변수: 값을 저장하고 그 값이 변할 수 있는 특성을 가진 공간을 의미

    식별자는 프로그래밍에서 이 공간을 구별하기 위한 이름

    • 변수: let age = 25 -> age가 변수, 저장된 값이 바뀔 수 있음
    • 식별자: age, totalAmout 단순히 어떤 데이터를 참조하거나 구별하기 위한 이름으로 값이 변할 수 있는 여부 x

     

    03. 변수 선언과 데이터 할당

    1) 변수를 선언하는 방법

    let a;

    이 코드의 의미는 'a'라는 이름의 빈 그릇을 만드는데 'a'라는 변수에 어떤 값도 할당되지 않았기 떄문에 변수 'a'의 값은 undefined

     

    2) 데이터 할당

    a = 'abc';

    이 코드는 'a'라는 변수가 이제 'abc'라는 값을 담게 되며 변수 'a'는 더 이상 빈 그릇이 아니라 'abc'라는 데이터를 담고 있는 그릇

     

    3) 변수 선언과 데이터 할당 한 번에 하기

    let a = 'abc';

    이 코드는 변수 'a'를 선언하고 동시에 'abc'라는 값을 바로 할당

     

    이 작업을 컴퓨터는 어떻게 처리할까?

    1. 변수선언: 메모리에서 빈 공간을 확보하고, 그 공간에 'a'라는 이름을 붙이기
    2. 데이터 할당: 실제로 'abc'라는 문자열은 별도의 공간에 저장되고, 변수 'a'는 이 문자열이 저장된 공간의 주소를 기억

     

    이렇게 하면 같은 데이터를 여러번 사용하더라도 메모리 공가을 절약할 수 있고, 데이터가 많이 바뀌거나 큰 경우에도 변수와 데이터를 분리해서 관리하는 것이 효율적

     

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

     

    1) 불변값: 한 번 만들어지면 그 값이 변경되지 않는 데이터

    자바스크립트에서 불변값은 원시 타입 (Number, String, Boolean, nul,, undefined, Symbole)

    let a = 10;
    a = 20;

    여기서 숫자 10이 20으로 바뀌는 게 아니라, 숫자 20이 새롭게 생성되어 'a'에 할당된 것. 숫자 10은 여전히 원래의 값으로 존재함

     

    2) 가변값: 생성된 후에도 내용이 변경될 수 있는 데이터

    자바스크립트에서 객체(Object)와 배열(Array)은 가변값

    let person = {
        name: "Alice",
        age: 25,
    };
    
    person.age = 26;

    person이라는 변수는 객체를 가리키고 있는 것으로, person 변수 아에 객체가 들어가있는것이 아니라

    객체가 메모리에 저장된 위치(주소)를 가리키고 있는 것

     

    예를 들어

    person은 주소, 주소는 집 위치를 알고 있고

    age의 속성값을 바꾸는 건 가구를 바꾼다고 생각하면 집 주소는 그대로지만, 집 안의 가구는 변할 수 있음

     

    3) 변수 복사 비교

    // 기본형
    let a = 10
    let b = a;
    b = 15;
    
    // 참조형
    let obj1 = {c: 10, d: 'ddd'};
    let obj2 = obj1;
    obj.c = 20;

     

    기본형 데이터:

    1. a는 메모리의 빈공간을 확보하고 그 공간에 10을 저장한 것으로 이때, a 변수는 10을 직접 가리킨다.
    2. b 변수는 a의 값을 복사해서 메모리의 새로운 공간에 10을 저장. 이때, a와 b는 각각 독립적인 값을 가지고 있음
    3. b의 값이 15로 변경되지만, a의 값은 여전히 10

     

    참조형 데이터:

    1. obj1 변수는 객체를 가리키고 있으며, 객체 자체는 메모리의 별도 공간에 저장되어있고 obj1은 객체가 저장된 메모리의 주소를 가리킨다.
    2. 그렇기 때문에 obj2는 obj1의 주소값을 복사하여 obj1과 obj2는 같은 주소값을 가리키게 된다.
    3. obj2를 통해 c의 속성값을 20으로 변경하면, 같은 객체를 참조하고 있기 떄문에 obj1에도 변경사항이 반영된다. 
    a !== b
    obj1 === obj2

     

    05. 불변 객체

    • 한 번 생성되면 그 내용을 변경할 수 없는 객체
    • 객체의 속성이나 데이터를 수정하려고 할 떄, 기존 객체를 직접 변경하는 대신 새로운 객체를 만들어 변환

    React같은 프레임워크를 사용해봤으면, 상태 변화에 따라 UI가 업데이트되는데 불변 객체를 사용하면 상태가 변경되었는지를 쉽게 판단할 수 있기 때문에 성능이 향상될 수 있으며, 원본 객체가 변경되지 않도록 하고 싶을 때 유용하다.

     

    let user = {name: 'Jaenam', gender: 'male'};
    
    fucntion changeNmae(user, newName) {
        let newUser = user;
        newUser.name = newName;
        return newUser;
    };
    
    let user2 = changeName(user, 'Jung');
    
    console.log(user.name);  // 'Jung'
    console.log(user2.name);  // 'Jung'
    console.log(user === user2);  // true (두 변수는 같은 객체를 가리킴)

    changeName 함수에서 user 객체를 newUser에 할당 후 newUser.name을 'Jung'으로 변경하고 있다.

    newUser는 단순히 user객체를 참조하고 있으며 newUser의 name 속성을 변경하면, 원본 user객체의 name 속성도 함께 변경된다.

    따라서 newUser객체의 name 속성만 변경하려고 했지만, 원본 객체인 user도 같이 변경된다는 문제가 발생한다.

     

    이런 이유로 불변객체를 생성하려면 객체의 속성을 변경할 때마다 새로운 객체를 만들어야한다.

     

    1) 스프레드 연산자 (Spread Operator)

    let user = {name: 'Jaenam', gender: 'male'};
    
    fucntion changeNmae(user, newName) {
        return { ...user, name: newName };
    };
    
    let user2 = changeName(user, 'Jung');
    
    console.log(user.name);  // 'Jaenam'
    console.log(newUser.name);  // 'Jung'
    console.log(user === newUser);  // false

    스프레드 연산자는 객체의 모든 속성을 복사해서 새로운 객체를 만드는 역할

    예를 들어, {...user}는 {name: 'Jaenam', gender: 'male'}과 동일한 속성을 가진 새로운 객체를 생성

     

    위 코드는 user 객체의 모든 속성을 새로운 객체로 복사하고, name 속성을 newName으로 덮어씌운 것으로

    이 과정에서 name 속성만 변경되고 나머지 속성은 유지 된다.

     

    2) 얕은 복사와 깊은 복사

    얕은 복사: 객체의 첫 번째 수준에 있는 속성들만 복사, 기본형 데이터는 복사되지만 참조형 데이터는 그 주솟값을 복사

    깊은 복사: 객체 내에 있는 모든 속성, 중첩된 객체나 배열까지도 완전히 새로운 복사본 생성

     

    let original = {
      name: 'Alice',
      details: {
        age: 25,
        city: 'New York'
      }
    };
    
    let shallowCopy = {...original};
    shallowCopy.name = 'Bob'; // 얕은 복사된 객체의 'name' 변경
    
    console.log(original.name); // 'Alice' (원본의 'name'은 변경되지 않음)
    console.log(shallowCopy.name); // 'Bob' (복사본의 'name'은 변경됨)
    
    shallowCopy.details.city = 'Los Angeles'; // 중첩된 객체의 값 변경
    
    console.log(original.details.city); // 'Los Angeles' (원본도 변경됨)
    console.log(shallowCopy.details.city); // 'Los Angeles' (복사본도 동일)

    스프레드 연산자로 shallowCopy는 origin의 얕은 복사본 생성

    그래서 name의 속성을 바꿔도 원본 객체에 영향을 미치지 않지만, details 속성처럼 한 단계 더 들어간 속성은 기존 데이터를 그대로 참조하고 있다.

     

    let original = {
      name: 'Alice',
      details: {
        age: 25,
        city: 'New York'
      }
    };
    
    function deepCopy(obj) {
      return JSON.parse(JSON.stringify(obj)); // 간단한 깊은 복사 방법
    }
    
    let deepCopyObj = deepCopy(original);
    deepCopyObj.details.city = 'Los Angeles'; // 깊은 복사된 객체의 'city' 변경
    
    console.log(original.details.city); // 'New York' (원본의 'city'는 변경되지 않음)
    console.log(deepCopyObj.details.city); // 'Los Angeles' (복사본의 'city'만 변경됨)

    객체를 JSON 문법으로 표현된 문자열로 전환했다가 다시 JSON 객체로 바꿔서

    deepCopy는 original 객체의 모든 단계 (중첩된 객체 포함)를 복사할 수 있다.

     

    (함수나 숨겨진 프로퍼티인 _proto, getter / setter 등과 같이 JSON으로 변경할 수 없는 프로퍼티는 무시)

     

    06. undefined와 null

    자바스크립트에서 'null'과 undefined는 '없음'을 나타내지만, 그 의미와 사용 목적이 다르다


    1) undefined: 정의되지 않음

    // case 1
    let = a;
    
    // case 2
    let obj = {name: 'Joen'};
    
    // case 3
    function sayHello() {
    	console.log("hello")
    };
    
    let result = sayHello();

    - 변수 선언 후 초기화하지 않은 경우 자바스크립트는 그 변수에 undefined 깂을 자동으로 할당

    - 존재하지 않는 객체의 속성에 접근할 때

    - 반환 값(return 문)이 없는 함수는 자동으로 undefined 반환

     

    2) null: 값이 비어있음

    let a = null;
    console.log(a); // null

    - 의도적으로 비어있음을 나타내어 초기값으로 사용

     

     

    undefined와 null의 차이

    console.log(undefined == null); // true
    console.log(undefined === null); // false

    두 값은 비슷해보이지만, null을 사용할 떄는 명확히 '값이 없음을 의도'한다는 의미를 가지고 있음

    undefined는 값이 아예 정의되지 않아 자바스크립트가 기본적으로 부여하는 값이라면,

    null은 값이 없음을 의도적으로 나타내어 개발자가 명시적으로 할당하는 값.

     

     

     

    댓글