ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 딥다이브 let,const 키워드와 블록 레벨 스코프
    javaScript 2022. 6. 20. 13:47

    딥다이브

    let,const 키워드와 블록 레벨 스코프

    키워드 (keyword)

    자바스크립트에서 특정한 목적을 위해 사용하는 단어이다.

    • 문법상 어떤 역할을 하는 단어들이라고 이해하면 편하다.
    • 이런 키워드들은 전부 예약어로 지정되어 있다. ex) return , for , break ,function등등

    스코프(scope)?

    • 스코프(scope)는 변수에 접근할 수 있는 범위를 말한다.
    • 스코프는 크게 전역 스코프와 지역 스코프로 나눌 수 있다.
    • 전역 스코프(global)는 어디에서든 해당 변수에 접근 가능한 걸 의미한다.
    • 지역 스코프(local)의 경우, 한정적인 범위에서 해당 변수에 접근이 가능하다.

    지역 스코프 안에 함수 스코프블록 스코프가 있으며 이 둘에 대해서 알아보도록 하자

    함수 스코프(function scope)

    함수에 의해서 생기는 유효 범위

    오로지 함수의 코드블록만을 지역 스코프로 인정하고 따라서 함수 외부에서 var keyword 로 선언한 변수는

    코드 블록 내에서 선언해도 모두 전역변수가 된다.

    (의도치 않게 먼저 선언된 변수값이 변경이 된다)

    • 함수가 선언되면 하나의 스코프(접근 범위)가 발생하는데 이걸 함수스코프라고 한다.
    • 함수 몸체에 선언한 변수는 해당 함수 안에서만 접근할 수 있음
    • 함수 스코프는 함수에서 선언한 변수는 해당 함수 내에서만 접근 가능하다는 걸 의미한다.

    블럭 스코프(block scope)

    블록에 의해 생기는 유효 범위

    모든 코드 블록 (함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

    { }

    • 블록이 생성될때 새로운 스코프가 생성
    • 자바스크립트는 원래 함수스코프를 따르지만, let과 const의 등장이후로 블록스코프형성도 가능해짐

    let ,const를 도입하게 된 배경

    ES5까지 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이었다. var 키워드로 선언된 변수는 아래와 같은 특징이 있다. 이는 다른 언어와는 다른 특징으로 주의를 기울이지 않으면 심각한 문제를 일으킨다.

    1. 함수 레벨 스코프(Function-level scope)
      • 함수의 코드블록만을 스코프로 인정한다. 따라서 전역 함수 외부에서 생성한 변수는 모두 전역 변수이다. 이는 전역 변수를 남발할 가능성을 높인다.
      • for 문의 변수 선언문에서 선언한 변수를 for 문의 코드 블록 외부에서 참조할 수 있다.
      • 자바스크립트는 함수 레벨 스코프를 사용한다. 즉, 함수 내에서 선언된 매개변수와 변수는 함수 외부에서는 유효하지 않다.
    2. var 키워드 생략 허용
      • 암묵적 전역 변수를 남발할 가능성 크다.
    3. 변수 중복 선언 허용
      • 의도하지 않은 변수값의 변경이 일어나 혼란을 높일 수 있다.
    4. 변수 호이스팅
      • 변수를 선언하기 이전에 참조할 수 있다.
      ES6는 이러한 var 키워드의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.1.변수 중복 선언 금지이때 변수를 중복 선언하면서 값까지 할당했다면 의도치 않게 먼저 선언된 변수 값이 재할당되어 변경되는 부작용이 발생한다.
      var foo = 123;
      var foo = 456; //중복선언허용
      
      let bar = 123; 
      let bar = 456; //문법 에러
      
      
      함수레벨스코프 함수 내에 선언된 변수는 함수내에서만 유효 , 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역변수이며, 함수 외부에서 선언한 변수는 모두 전역변수이다.블록레벨스코프를 따르지 않는 var 키워드의 특성 상 , 코드 블록 내의 변수 foo 는 전역변수이다. 그런데 foo 가 선언되어 있고 var 키워드를 사용하여 선언한 변수는 중복 선언이 허용되므로 위의 코드는 문법적으로 문제가 없다.
      let foo = '민수'; // 전역 변수
      {
      let foo = '영완'; // 지역변수
      let bar = '영완'// 지역변수
      }
      console.log(foo); //'민수'
      consol.log(bar); // ReferenceError : bar is not defined자바
      
      let 키워드로 선언된 변수는 블록 레벨 스코프를 따른다.
    5. var foo = '민수'; // 전역 변수 (1) console.log(foo);// '민수' { var foo = '영완'; // 전역 변수 (2); } console.log(foo); //'영완'
    6. 코드블록내에 선언된 변수 foo 는 블록레벨 스코프를 갖는 지역변수이다. 전역에서 선언된 변수 foo 와는 다른 별개의 변수이다. 또한 bar도 블록레벨스코프를 갖는 지역변수이다. 따라서 전역에서는 변수 bar를 참조 할 수 없다.
    7. 단,코드 블록 내의 변수 foo(2) 는 전역변수이기 떄문에 전역에서 선언된 전역변수 foo(1)의 값 ‘민수’를 새로운 ‘영완’으로 재할당 하여 덮어쓴다.
    8. 블록레벨스코프 모든 코드 블록 (함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
    9. 하지만 let 키워드는 동일한 이름 갖는 변수를 중복해서 선언할 수 없다. 변수를 중복 선언하면 문법에러 SyntaxError 발생.
    10. var 키워드로 동일한 변수를 중복 선언하면 아무런 에러가 발생하지 않는다.
    11. let 키워드

    호이스팅

    호이스팅이란 함수 안의 변수 선언을 모두 최상단으로 끌어 올려주는 JS 고유의 독특한 기능입니다

    ( var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다).

    자바스크립트는 ES6에서 도입된 let, const 를 포함하여 모든 선언을 호이스팅한다.

    변수 foo 가 선언되기 전에 console.log로 출력을 행하더라도 에러가 발생하지 않고, undefined를 출력합니다. 그 이유는 JS가 선언문 var foo 를 소스코드 최상단으로 호이스팅했기 때문이다.

    var의 호이스팅
    
    //이 시점에는 변수 호이스팅에 의해 이미 foo 변수가 선언되었다.(1. 선언 단계)
    // 변수 foo는 undefined로 초기화된다.(2. 초기화 단계)
    
    console.log(foo); //undefinded
    
    //변수에 값을 할당(3. 할당 단계)
    foo = 123;
    
    console.log(foo);//123
    
    //변수 선언은 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 실핼된다.
    var foo;
    
    --------------------------------------------------------
    /* 호이스팅 된 소스 코드 */
    var foo; 
    console.log(foo);
    foo = 123;
    console.log(foo);
    

    var 키워드로 선언한 변수는 런타임 이전에 선언 단계와 초기화 단계가 함께하고

    let키워드로 선언한 변수는 선언 단계초기화 단계가 분리되어 진행됩니다.

    let키워드로 선언한 변수는 일시적 사각지대(TDZ Temporal Dead Zone)가 발생

    변수 라이프 사이클

    선언 단계 (Declaration phase)

    • 변수를 실행 컨텍스트의 environmentRecord에 등록
    • environmentRecord는 스코프가 참조하는 대상

    초기화 단계 (Initialization phase)

    • environmentRecord에 등록 된 변수를 위한 메모리를 확보
    • 이 단계에서 변수는 undefined로 초기화

    할당 단계 (Assignment phase)

    • undefined로 초기화 된 변수에 실제 값을 할당

    console.log(foo);//ReferenceError : foo is not defined
    let foo; 
    

     

    const 키워드

    선언과 초기화

    const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화 해야한다.

    초기화 :데이터를 변수(공간)에 집어넣는 과정

    const foo = 1;
    

    그렇지 않으면 다음과 같이 문법에러가 발생한다.

    선언 + 할당이 같이 이루어져야한다.

    const foo; // StntaxError : missing initiallizer in const declaration
    

    const 키워드로 선언한 변수는 let 키워드로 선언한 변수와 마찬가지로 블록 레벨 스코프를 가지며 변수 호이스팅이 발생하지 않는것처럼 동작한다.

    {
    //변수 호이스팅이 발생하지 않는것처럼 동작한다.
    console.log(foo);//ReferenceError : Cannot access 'foo' before initialization
    const foo = 1;
    console.log(foo);//1
    }
    
    //블록 레벨 스코프를 갖는다.
    console.log(foo);//ReferenceError : foo is not defined
    

    재할당 금지

    var 또는 let 키워드로 선언한 변수는 재할당이 자유로우나 const 키워드로 선언한 변수는 재할당이 금지된다.

    const foo =1;
    foo=2; //TypeError : Assignment to constant variable.
    

    상수

    상수는 가독성과 유지보수의 편의를 위해 적극적으로 사용해야 한다.

    네이밍 잘하세요

    // 10의 의미를 알기 어렵기 때문에 가독성이 좋지 않다.
    if (rows > 10) {
    }
    
    // 값의 의미를 명확히 기술하여 가독성이 향상되었다.
    const MAXROWS = 10;
    if (rows > MAXROWS) {
    }
    

    조건문 내의 10은 어떤 의미로 사용했는지 파악하기 곤란한데 네이밍이 적절한 상수로 선언하면 가독성과 유지보수성이 향상된다.

    const 는 객체에서도 사용가능하다. 이때도 재할당으 ㄴ금지된다.

    const obj = {foo : 123};
    obj = {bar : 456}; // TypeError : Assignment to constant variable.
    

    const 는 재할당이 금지된다.

    하지만 const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 있는데 변경 불가능한 값인 원시값은 재할당 없이 변경할 수 있는 방법이 없지만 변경 가능한 값인 객체는 재할당 없이도 직접 변경이 가능하기 때문이다.

    const person ={
    name : 'MINSU'
    };
    
    //객체는 변경 가능한 값이다. 따라서 재할당 없이 변경 가능하다.
    
    person.name = 'JUN'
    
    console.log(person);//{name:'JUN'}
    
    

    var vs let vs const

    변수 선언에서는 기본적으로 const를 사용하고 let은 재할당이 필요한 경우에 한정해 사용하는것이 좋다. const 키워드를 사용하면 의도치않은 재할당을 방지하기때문에 좀 더 안전하다.

    var , let , const 키워드는 다음과 같이 사용하는 것을 권장한다.

    • ES6를 사용한다면 var는 쓰지 않는다
    • 재할당이 필요한 경우에 한정해 let 키워드를 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.
    • 변경이 발생하지 않고 읽기 전용으로 하는 원시값과 객체에는 const 키워드를 사용한다. const 키워드는 재할당을 금지하므로 var, let 보다 안전하다.

    변수를 선언하는 시점에는 재할당이 필요할지 잘 모르는 경우가 많지만 객체는 의외로 재할당 하는 경우가 드물다 따라서 변수를 선언할 때는 일단 const 키워드를 사용하자 반드시 재할당이 필요하다면 그때 Const를 let 키워드로 변경해도 된다.

    'javaScript' 카테고리의 다른 글

    method (forEach,map,filter,reduce)정리  (0) 2023.02.21
    비동기 프로그래밍 Ajax  (0) 2022.07.03
    딥다이브 빌트인 객체  (0) 2022.06.21
    딥다이브 7장 연산자  (0) 2022.06.17
    Hoisting  (0) 2022.06.10
Designed by Tistory.