자바스크립트: 동적 타이핑과 호이스팅

괴발개발·2025년 1월 10일

LG CNS AM Inspire Camp 1기

목록 보기
11/17
post-thumbnail

1. 동적 타이핑(dynamic typing)

  • 변수에 데이터가 대입되는 시점에 변수의 자료형이 결정
  • 자바는 int i = 10;과 같이 변수 선언 시 데이터 타입 지정
  • 자바스크립트는 var i = 10;과 같이 변수를 선언할 때 데이터 타입을 지정하지 않고, 변수에 값이 할당되는 시점에 할당되는 값에 따라 데이터 타입 결정
  • 자바는 int i = "abc";과 같이 변수의 데이터 타입과 할당되는 값의 데이터 타입이 일치하지 않으면 오류 발생
  • 자바스크립트는 var i = "abc";과 같이 변수가 할당되는 시점에 데이터 타입이 결정되므로 정상적으로 동작
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>자바스크립트 자료형</h1>
        <script>
            // number type
            let n1 = 1234;
            let n2 = 56.78;    
            console.log(n1, typeof(n1));    // 1234 number
            console.log(n2, typeof(n2));    // 56.78 number
    
            // string type
            let s1 = 'Hello';
            let s2 = "World";
    
            // 이스케이프 처리
            let s3 = 'Hello, \'Inho\'';
            let s4 = "Hello, \"Inho\"";
    
            // 템플릿 문자열(template literal)
            // https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals
            let name = 'Inho';
            let age = 23;
            let hello1 = '이름은 "' + name + '"이고, 나이는 ' + age + '세 입니다.';
            console.log(hello1);
    
            let hello2 = `이름은 "${name}"이고, 나이는 ${age}세 입니다. 내년에에는 ${age + 1}세가 됩니다.`;
            console.log(hello2);
    
            // boolean type
            let b1 = true;
            let b2 = false;
            console.log(b1, typeof(b1));    // true boolean
            console.log(b2, typeof(b2));    // false boolean
    
            // falsy value
            console.log(Boolean(''));           // false
            console.log(Boolean(0));            // false    
            console.log(Boolean(-0));           // false         >   
            console.log(Boolean(null));         // false
            console.log(Boolean(undefined));    // false
            console.log(Boolean(NaN));          // false
            console.log(Boolean(false));        // false
    
            if (undefined) {
                console.log('undefined는 true');
            } else {
                console.log('undefined는 false');   // undefined는 false 출력
            }
    
            if (-1) {
                console.log('-1은 true');           // -1은 true 출력
            } else {
                console.log('-1은 false');
            }
    
            // null type
            let nullValue = null;
    
            // undefined type
            let u1;
            let u2 = undefined;
    
            // array type = 다양한 데이터 타입을 순서대로 모아놓은 것
            let arr1 = [1, 2, 3, 4, 5];
            let arr2 = [1, 2.3, 'hello', true, null, undefined, [1, 2, 3]];
            console.log(arr1[3]);   // 4
            console.log(arr2[5]);   // undefined
            arr1[3] = 100;
            console.log(arr1);      // [1, 2, 3, 100, 5]
    
            // object type = key와 value로 이루어진 데이터 타입
            //               key는 문자열 또는 심볼이어야 하고, 값은 모든 데이터 타입이 가능
            let obj1 = { a: 'apple', b: 'banana', c: 'cherry' };
            let obj2 = { name: 'Inho', age: 23, 'favorite colors': ['red', 'blue', 'green'] };
            console.log(obj1['a']); // apple
            console.log(obj1.a);    // apple
            console.log(obj2['favorite colors']);   // ['red', 'blue', 'green']
        </script>
    </body>
    </html>
  • 실행 결과

2. 호이스팅(var, let, const와 함수)

  • 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상
  • 호이스팅 MDN

2-1. var

  • 전역 변수로 값이 재선언되거나 업데이트 될 수 있다.
  • 다른 코드에서 값이 초기화 된 경우 의도치 않은 값이 출력될 수 있다.
  • 예시 코드
    <script>
      console.log(x1);	// undefined => x1 변수가 hoisting되어 선언된 것으로 처리
      var x1;
      console.log(x1);	// undefined
    </script>
  • 위의 코드는 내부적으로 아래와 같이 해석되어 실행된다.
    <script>
      var x1;
      console.log(x1);	// undefined
      console.log(x1);	// undefined
    </script>
    <script>
      console.log(x1);	// undefined
      var x1;
      console.log(x1);	// undefined
     
      x1 = 100;
      console.log(x1, typeof(x1));	// 100 'number'
    </script>

2-2. let

  • 동일 범위({블록} 단위) 내에선 업데이트는 될 수 있지만 재선언은 불가
  • 변수 선언은 호이스팅 되지만 값은 초기화될 수 없다.
  • 변수는 초기화되기 전까지 TDZ에 보관되어 참조할 수 없으므로 initialization 에러 발생
    ☑️ TDZ란? 변수가 선언되었지만 초기화되지 않은 상태로 존재하는 영역으로 이 영역에서 변수를 참조하려 하면 오류가 발생한다.
  • 예시 코드
    <script>
      console.log(x3);	// Cannot access 'x3' before initialization
      let x3 = 100;
      console.log(x3);	// 100
    </script>
    <script>
      let x3;			// 변수 선언이 호이스팅 되지만 초기화되진 않음
      					// => TDZ 보관 => 초기화되기 전에 참조할 수 없음
      console.log(x3);	// Cannot access 'x3' before initializtion
      x3 = 100;
      console.log(x3);	// 100
    </script>

2-3. const

  • 동일 범위({블록} 단위) 내에서만 접근 가능한 변경 불가능한 상수 선언형
  • let과 동일하게 호이스팅은 선언만 하고 초기화 기능을 하지 않는다.
  • TypeError 발생
  • 예시 코드
    <script>
      const a = 100;
      a = 200;	// Uncaught TypeError: Assignment to constant variable.
    </script>

✔️ let과 cosnt는 var와 달리 초기화되고 쓴다는 것을 보장해준다.

2-4. 함수 호이스팅

  • 함수 선언문 형식으로 함수를 정의하면 함수 정의 부분이 호이스팅 되어 위치와 관계 없이 호출 가능
    <script>	// 함수 자체가 scope로 호이스팅 되어 호출 가능
      hello();	//Hello, JavaScript!
      // 함수 선언문 형식으로 정의
      function hello() {
      	console.log("Hello, JavaScript!");
      }
      hello();	// Hello, JavaScript!
    </scipt>
  • 하지만 함수 표현식으로 함수를 정의하는 경우에는 함수 변수 선언 방식에 따라 오류가 생길 수 있다.

    2-4-1. var 키워드로 함수 변수 정의

    <script>
      hello();	// Uncaught TypeError: hello is not a function
      var hello = function() {
      console.log('Hello, JavaScript!');
      };
      hello();	// Hello, JavaScript!
    </script>
    • 호이스팅은 선언만 하고 초기화 기능을 하지 않으므로 var 선언까지만 인식 되고 hello() 함수를 연결할 수 없어 TypeError가 발생한다.
    • 내부적으로는 아래와 같이 해석
    <script>
      var hello;	// undefined 상태
      hello();		// Uncaught TypeError: hello is not a function
      hello = function() {
      	console.log('Hello, JavaScript!');
      };
      hello();		// Hello, JavaScript!
    </script>

    2-4-2. let 키워드로 함수 변수 정의

    <script>
      hello();	// Uncaught ReferenceError: Cannot access 'hello' before initialization
      let hello = function() {
      	console.log('Hello, JavaScript!');
      };
      hello();	// Hello, JavaScript!
    </script>
    • 참조가 불가능해 ReferenceError 발생
    • 내부적으로는 아래와 같이 해석
    <script>
      let hello;	// 초기화되기 전까지 TDZ에 머물러 있다.
      hello();		// Uncaught ReferenceError: Cannot access 'hello' before initialization
      hello = function() {
      	console.log('Hello, JavaScript!');
      };
      hello();		// Hello, JavaScript!
    </script>

0개의 댓글