모던 자바스크립트 DeepDive 6장

김규회·2024년 3월 25일
0

데이터 타입

  • 데이터 타입: 값의 종류
  • ES6은 7개의 데이터 타입을 제공
    • 원시 타입
      • 숫자
      • 문자열
      • 불리언
      • undefined
      • null
      • 심벌
    • 객체 타입
      • 객체, 함수, 배열 등

숫자 타입

  • 자바스크립트에는 int, double 등을 따로 구분하지 않고 하나의 숫자 타입만 존재한다.

    • 따라서 모든 숫자 타입은 실수로 처리되고, 정수만 표현하기 위한 데이터 타입은 별도로 존재하지 않는다.

      console.log(1 === 1.0);     //true
      console.log(3/2);           //1.5
    • 2진수, 8진수, 16진수를 표현하기 위한 데이터 타입을 제공하지 않기 때문에 이를 참조하면 모두 10진수로 해석된다.

      var bin = 0b01000001; 
      var oct = 0o101;
      var hex = 0x41;
      
      console.log(bin);  //65
      console.log(oct);  //65
      console.log(hex);  //65 
      console.log(bin === oct);  //true
      console.log(oct === hex);  //true
    • 무한대, 산술연산불가를 표현하기 위한 값도 존재한다.

      console.log(10/0);        //Infinity: 양의 무한대
      console.log(10/-0);       //-Infinity: 음의 무한대
      console.log(1*'String');  //NaN

      💡 Infinity 예외처리

      자바스크립트에는 0으로 나눈 결과를 표현하기 위한 값인 Infinity, -Infinity가 있기 때문에 이를 이용해 예외처리를 해 줄 수 있다(달리 말하면 프로그램이 오류를 내지 않고 Infinity로 표현해 버리기 때문에 해 줘야 한다 → 라고 나는 이해했는데 맞나유). 아래 코드 참고!!

      try {
      	var result = 10/0;
      	if(result == 'Infinity'){        //무한대일 경우 강제 예외 발생
      		throw 'DivideByZeroException';
      	}
      	alert(result);
      } catch(exception) {
      	alert(exception);
      }

문자열 타입

  • 문자열은 작은따옴표(’ ‘), 큰따옴표(” “), 백틱( )로 텍스트를 감싸서 표현할 수 있다.
    • 가장 일반적인 표기법은 작은따옴표
  • 다른 타입과 달리 문자열을 따옴표로 감싸는 이유는 토큰과 구별하기 위해서이다.
    • 즉, 따옴표로 감싸지 않으면 자바스크립트 엔진은 이를 키워드는 식별자 같은 토큰으로 인식한다.

      var str1 = 'hello';   //hello를 문자열로 인식
      var str2 = hello;     //hello를 식별자로 인식. ReferenceError: hello is not defined
  • 따옴표로 문자열을 감싸지 않는다면 공백문자도 포함시킬 수 없다.
  • 자바스크립트에서 문자열은 원시 타입이며, 변경 불가능한 값(immutable)이다.
    • 즉 한번 생성되면 변경할 수 없다. (자세한 사항은 11장에서)
    • cf) 대부분의 프로그래밍 언어에서 문자열은 배열이나 객체 타입
  • var score = 10;
  • var temp = `hello
  • my score is
  • ${name}` ;

템플릿 리터럴

  • ES6부터 템플릿 리터럴이라고 하는 새로운 문자열 표기법이 도입되었다.

    • 템플릿 리터럴은 멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등 편리한 문자열 처리 기능을 제공한다.

    • 템플릿 리터럴은 런타임에 일반 문자열로 변환되어 처리한다.

    • 백틱( )으로 감싸서 표현한다.

      //멀티라인 문자열(일반 문자열은 개행이 허용되지 않기 때문에 공백을 표현하려면 백슬래시 사용)
      var multiLine = `hello
      world`;                              
      
      //표현식
      var expression = `1 + 2 = ${1 + 2}`;  

      💡 라인 피드와 캐리지 리턴

      개행 문자에는 라인 피드와 캐리지 리턴, 2가지가 있다(둘다 과거 타자기에서 유래).
      라인 피드(\n): 커서를 정지한 상태에서 종이를 한 줄 올리기
      캐리지 리턴(\r): 종이를 움직이지 않고 커서를 맨 앞줄로 이동
      CRLF: 캐리지 리턴(커서를 맨 앞줄로 이동) 후 라인 피드(종이를 한 줄 올리기)하는 방식으로 개행

      운영체제마다 개행 방식이 조금씩 다르다.
      윈도우: CRLF(캐리지리턴, \r + 라인피드, \n)
      유닉스: LF(라인피드, \r)
      macOS: 버전 9까지는 CR(캐리지리턴, \r), 10부터는 LF(라인피드, \n)
      그래서 서로 다른 운영체제에서 작성한 텍스트 파일은 서로 개행 문자를 인식하지 못한다. 다만 대부분의 텍스트 에디터는 운영체제에 맞게 개행문자를 자동 변환해주므로 큰 문제는 없다.

      자바스크립트에서 LF와 CR 둘 다 개행을 의미하지만, 대부분 라인 피드(\n)를 사용해 개행한다.

      💡 태그드 템플릿

      템플릿 리터럴의 발전된 형태로써, 함수 형태로 사용할 수 있다. 이 문법은 문자열에서 userName, age와 같은 변수(동적 데이터)와 “hi”, “hello” 같은 문자열(정적 데이터)를 구분지을 수 있다. 아래 코드 참고!!

      const meal = 'dinner';
      const taste = 'good';
      
      function getSnackTaste(string, meal, taste) {
          console.log(string);
          console.log(meal);
          console.log(taste);
      }
      
      getSnackTaste`Today, ${meal} is ${taste}`;
    • 이렇게 함수에 템플릿 리터럴을 넣어 주면, 동적 데이터와 정적 데이터를 파싱해서 보여준다.

      const meal = 'dinner';
      const taste = 'good';
      
      function getSnackTaste(string, ...values) {
          console.log(string);
          console.log(values);
      }
      
      getSnackTaste`Today, ${meal} is ${taste}`;
    • Rest Parameters를 활용하면 파라미터(동적데이터)가 아무리 늘어나도 확장성 있게 코드를 사용할 수 있다.

      💡 스타일드 컴포넌트

      태그드 템플릿 문법을 적극적으로 사용하는 라이브러리 중 하나가 styled-components이다. 정적데이터와 동적데이터를 자동으로 파싱해주는 템플릿 리터럴을 활용해 css 스타일에 관련된 값들을 동적데이터로 넣을 수 있다. (찾아보는 김에 개발자 도구에 외계어 뜨는 이유도 찾아보려 했지만… 못찾음) → css in js가 애초에 자바스크립트에서 편하게 쓰려고 만든거라 원래 css가 아님. 컴파일되어버린 css가 개발자도구에 떠서그럼
      성능 면에서는 순수css가 좋음(컴파일 단계를 생략할 수 있어서)
      근데 순수css를 안 쓰는 이유: 코드가 더러워짐(따로 css파일생성), 개발자 입장에서 불편함(다 일일이 고쳐야해서)

      const Btn = styled.button `
      	height: 2rem;
      	font-size: 1rem;
      	color: ${props => props.color};
      	background: ${props => props.background};
      `

불리언 타입

  • 불리언 타입의 값은 논리적 참, 거짓을 나타내는 true와 false 뿐이다.
  • 주로 참/거짓으로 구분되는 조건에 의해 프로그램의 흐름을 제어하는 조건문에서 자주 사용한다.
  • 1byte임(1bit밖에 안 필요할 것 같지만 컴퓨터의 최소 연산 단위가 1byte라서)

undefined 타입

  • undefined 타입의 값은 undefined가 유일하다.
  • 개발자가 의도적으로 할당하기 위한 값이 아니라, 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값이다. 즉, 변수를 참조했을 때 undefined가 반환된다면 참조한 변수가 초기화되지 않은 변수라는 것을 알 수 있다.
  • 개발자가 의도적으로 변수에 값이 없다는 것을 명시하고 싶을 때는 undefined가 아니라 null을 할당한다.
  • undefined와 null을 구별해 의도적으로 비운 것과, 의도와 다르게 초기화되지 않은 케이스를 구별

null 타입

  • null 타입의 값은 null이 유일하다.
  • 변수에 값이 없다는 것을 의도적으로 명시할 때 사용한다.
    • 변수에 값이 없다 = 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다(참조를 명시적으로 제거)
    • 해당 값에 대한 참조가 어디에도 없으면 → 그 메모리 공간을 가비지 콜렉터가 해제해도 괜찮다!
  • 함수가 유효한 값을 반환할 수 없는 경우에도 명시적으로 null을 반환한다.

심벌 타입

  • 심벌 타입은 ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시 타입의 값이다.
  • 심벌 값은 다른 값과 중복되지 않는 유일무이한 값으로, 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
  • 심벌 이외의 원시 값은 리터럴을 통해 생성하지만, 심벌은 Symbol 함수를 호출해 생성한다. 이때 생성된 심벌 값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.
    //심벌 값 생성
    var key = Symbol('key');
    console.log(typeof key);   //symbol
    
    //객체 생성
    var obj = {};
    
    //이름이 충돌할 위험이 없는 유일무이한 값인 심벌을 프로퍼티 키로 사용
    obj[key] = 'value';
    console.log(obj[key]);   //value
  • 자세한 사항은 33장

객체 타입

  • 객체 타입은 11장에서 다룬다.

데이터 타입의 필요성

  • 데이터 타입에 의한 메모리 공간의 확보와 참조
    • 메모리에 값을 저장하려면 먼저 확보해야 할 메모리 공간의 크기를 결정해야 하는데, 데이터 타입으로 값의 종류를 알려 주면 그에 알맞게 확보해야 할 메모리 공간의 크기를 결정할 수 있다. (종류 구분없이 똑같은 메모리 공간을 할당하면 가장 큰 것에 맞추어야 하니 메모리 낭비임!)
    • 메모리의 값을 참조할 때, 변수가 가리키고 있는 메모리 공간 주소로부터 몇 바이트를 읽어야 하는지를 데이터 타입을 통해 알 수 있다. 예를 들어 숫자 타입의 경우, 변수가 가리키는 메모리 주소로부터 8바이트만 읽어야 정확한 숫자 값을 읽어올 수 있다(8바이트보다 적게, 혹은 많게 읽어오면 그만큼 데이터를 덜 읽거나, 다른 데이터까지 같이 읽어버리므로 값이 훼손됨). 이때 데이터 타입을 통해 숫자 타입임을 인식하고, 정확히 8바이트만 읽어온다.
    • 데이터 타입에 의한 값의 해석
      • 모든 값은 2진수 형태로 저장된다. 따라서 읽어올 때도 2진수 형태로 읽어들여진다. 이 2진수를 어떻게 해석해야 하는지를 데이터 타입이 결정해준다.
      • ex) 같은 0100 0001 이라도 데이터 타입이 숫자면 65로 해석되고, 문자열이면 ‘A’로 해석된다.

동적타이핑

  • 정적 타입 언어
    • 명시적 타입 선언: C와 JAVA 같은 정적 타입 언어는 변수를 선언할 때 데이터 타입을 사전에 선언해야 하며, 한번 타입을 결정했으면 이후 변수의 타입을 변경할 수 없다.
    • 컴파일 시점에 타입 체크(선언한 데이터 타입에 맞는 값을 할당했는지 검사하는 처리)를 수행하여, 타입 체크를 통과하지 못했다면 에러를 발생시키고 프로그램 실행 자체를 막는다.
    • 이는 타입의 일관성을 강제함으로써 안정적으로 코드를 구현하고, 런타임에 발생하는 에러를 줄인다.
  • 동적 타입 언어
    • 타입 추론: 자바스크립트는 변수를 선언할 때 타입을 선언하지 않는다. 값을 할당하는 시점에 변수의 타입이 동적으로 결정되기 때문이다.
    • 따라서 어떤 데이터 타입의 값이든 자유롭게 할당할 수 있다. 또한 언제든지 재할당을 통해 변수의 타입을 자유롭게 변경할 수 있다.
    • 즉, 자바스크립트에서 변수는 타입을 갖지 않는다. 값이 타입을 갖는다. 따라서 변수에 할당되어 있는 값에 의해 변수의 타입이 동적으로 결정되는 것이다.
  • 동적 타입 언어는 편리하긴 하지만, 그만큼 위험성이 있다.
    • 변수 값은 언제든지 변경될 수 있기 때문에 복잡한 프로그램에서는 변화하는 변수 값을 추적하기 어려울 수 있다. 그런데 동적 타입 언어에서는 값뿐만 아니라 타입까지 동적으로 변화하니 값을 확인하지 못하면 타입도 확신할 수가 없다.
    • 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되기도 한다. 즉, 숫자 타입을 의도했는데 사실은 문자열 타입으로 실행되고 있을 수도 있다. 즉, 유연성은 높으나 신뢰성은 떨어진다.
      • 타입을 설정안해주면 엔진이 자동으로 any로 설정해버림. 타입을 만약 설정하게 되면 타입스크립트가 되는 것(좀더 안정적).
  • 따라서 가독성 높은 코드를 쓰는 것이 더욱 필요하다.
    • 변수는 꼭 필요한 경우에 한해 제한적으로 사용한다(재할당에 의해 언제든지 변경될 수 있으므로). → 자바스크립트는 타입을 잘못 예측해 오류가 발생할 가능성이 크므로 변수의 개수가 많을수록 오류 발생 확률도 높아진다.
    • 변수 스코프는 최대한 좁게 만든다.
    • 전역변수는 최대한 사용하지 않도록 한다. 전역변수는 어디서든지 값이 변경될 수 있기 때문에 의도치 않게 값이 변경될 가능성도 높고, 다른 코드에 영향을 줄 가능성도 높다.
    • 변수보다는 상수를 사용해 값의 변경을 억제한다. (usually const, sometimes let, never var)
    • 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다. 특히 유효 범위가 넓을수록 명확한 이름을 명명해야 한다.
profile
프론트엔드 Developer

0개의 댓글