ABOUT ME

Today
Yesterday
Total
  • 3.2 JavaScript 스코프
    코드스테이츠 2023. 3. 2. 20:47

    스코프 개요

    JavaScript에서 이야기하는 스코프 역시 무언가 제한된 범위를 잘 들여다보기 위해 사용되는 개념

    컴퓨터 공학, 그리고 JavaScript에서의 스코프는 "변수의 유효범위"로 사용

     

    💁‍♀️ 콘솔에 순서대로 출력되는 결과는 무엇인가요?

    let username = 'kimcoding';
    if (username) {
      let message = `Hello, ${username}!`;
      console.log(message); // ?
    }
    
    console.log(message); // ?
     

    A. "Hello, kimcoding!" "Hello, kimcoding!"

    B. "Hello, kimcoding!" ReferenceError

    C. ReferenceError "Hello, kimcoding!"

     

    🔈 해설

    정답 B

    4번째 줄에서 message를 출력할 때는, 3번째 줄의 username을 바깥 스코프에서 가져왔으므로 정상적으로 출력됩니다.

    그러나, 6번째 줄에서는 message라는 변수 자체가 안쪽 스코프에 선언되어 있으므로, 바깥쪽에서는 접근할 수 없습니다.

     

     


    💁‍♀️ 콘솔에 순서대로 출력되는 결과는 무엇인가요?

    let greeting = 'Hello';
    function greetSomeone() {
      let firstName = 'Josh';
      return greeting + ' ' + firstName;
    }
    
    console.log(greetSomeone()); // ?
    console.log(firstName); // ?

     

    A. 'Hello Josh' 'Josh'

    B. ReferenceError 'Josh'

    C. 'Hello Josh' ReferenceError

     

    🔈 해설

    정답 C

    greeting 변수는 바깥 스코프에 정의되어 있으므로, 함수 안쪽에서 사용할 수 있습니다. 따라서 greeting 변수와 firstName 변수의 조합에 의해 'Hello Josh' 문자열이 출력됩니다.

    반면에, firstName 변수는 안쪽 스코프에 정의되어 있으므로 바깥쪽에서는 접근이 불가능합니다. 따라서 ReferenceError를 냅니다.

     


    스코프의 정의

    "변수 접근 규칙에 따른 유효 범위"

    1. 안쪽 스코프에서 바깥쪽 스코프로는 접근할 수 있지만 반대는 불가능합니다.
    2. 스코프는 중첩이 가능하다.
    3. 가장 바깥의 스코프는 전역 스코프 (Global Scope) <-> 전역이 아닌 다른 스코프는 전부 지역 스코프(local Scope)
    4. 지역 스코프에서 선언한 변수는 지역 변수, 전역 스코프에서 선언한 변수는 전역 변수
    5. 지역 변수는 전역 변수보다 더 높은 우선순위를 가짐

    💁‍♀️ 순서대로 콘솔에 출력되는 결과는?

    let name = '김코딩';
    
    function showName() {
      let name = '박해커'; // 지역 변수
      console.log(name); // 두 번째 출력
    }
    
    console.log(name); // 첫 번째 출력
    showName(); // 두 번째 출력
    console.log(name); // 세 번째 출력

     

    A. 김코딩 박해커 김코딩

    B. 김코딩 박해커 박해커

    C. 박해커 박해커 박해커

     

    🔈 해설

    정답 A

    첫 번째 출력은 첫째 줄에서 전역 변수로 선언된 name을 가져옵니다. 이는, showName 함수 안쪽에 선언된 지역 변수 name은 애초에 스코프 규칙에 의해 접근할 수 없기 때문입니다. 따라서 "김코딩"을 출력합니다.

    반면, 두 번째 출력은 함수 안에서 선언한 name이라는 지역 변수에 접근하고 있습니다. 변수 이름이 전역 변수와 똑같지만, 지역 변수가 전역 변수보다 우선순위가 높으므로, 지역 변수 name이 출력되는 것입니다. 동일한 변수 이름으로 인해 바깥쪽 변수가 안쪽 변수에 의해 가려지는(shadow) 이러한 현상을 쉐도잉(variable shadowing)이라고 부릅니다.

    두 번째 출력은 "박해커"입니다.

    세 번째 출력은 첫 번째 출력과 마찬가지로 전역 변수 name을 출력합니다. 지역 변수에 선언된 name 변수는 안쪽 스코프이므로 접근이 불가능합니다. 따라서 "김코딩"을 출력합니다.

     


    💁‍♀️ 순서대로 콘솔에 출력되는 결과는? <오답노트>

    let name = '김코딩';
    
    function showName() {
      name = '박해커';
      console.log(name); // 두 번째 출력
    }
    
    console.log(name); // 첫 번째 출력
    showName();
    console.log(name); // 세 번째 출력

     

    A. 김코딩 박해커 김코딩

    B. 김코딩 박해커 박해커

    C. 박해커 박해커 박해커

     

    🔈 해설

    정답 B

    앞서 문제와는 다르게, 세 번째 줄에서 let 키워드를 사용한 선언이 존재하지 않습니다.

    이는, '박해커'라는 값으로 할당하고 있는 name 변수는 전역에 선언된 name 변수를 그대로 사용하겠다는 의미입니다.

    지역 스코프에서 새로 선언되지 않으면 그냥 같은 변수입니다.

    따라서 showName 함수가 실행되기 전, 처음에는 '김코딩'을 출력하고, 그 이후에는 전역변수 name의 값이 바뀌기 때문에 두 번째 및 세 번째 출력에 '박해커'가 출력됩니다.

     


     

    스코프는 두 가지 종류가 있습니다.

    1. 블록 스코프 block scope

    중괄호를 기준으로 범위가 구분된다.

    2. 함수 스코프 function scope 

    function 키워드가 등장하는 함수 선언식 및 함수 표현식은 함수 스코프를 만든다.

    ※ 화살표 함수

    블록스코프로 취급됨

     

    var 키워드와 let 키워드

    • var 키워드로 정의한 변수는 블록 스코프를 무시하고, 함수 스코프만 따릅니다. 
    • 그러나, 모든 블록 스코프를 무시하는 건 아닙니다. 화살표 함수의 블록 스코프는 무시하지 않습니다.
    • 함수 스코프는 함수의 실행부터 종료까지이고, var 선언은 함수 스코프의 최상단에 선언됩니다. 
    • 선언 키워드 없는 선언은 최고 스코프에 선언됩니다.
      함수 내에서 선언 키워드 없는 선언은, 함수의 실행 전까지 선언되지 않은 것으로 취급합니다.
    • 보통 코드를 작성할 때 블록은 들여쓰기가 적용되고, 그 구분이 시각적으로 분명합니다. 따라서 많은 사람들은 블록 스코프를 기준으로 코드를 작성하고, 생각하기 마련입니다. 그러나 var는 이 규칙을 무시하므로, 코드를 작성하는 사람이 블록 스코프/함수 스코프에 대한 이해가 없으면 코드가 다소 혼란스러울 수 있습니다.
    • 따라서, var 보다는 let 으로 변수 선언을 하는 것을 권장합니다.
    • var 를 사용하지 않는다 해도, 함수 스코프는 let으로 선언된 변수의 접근 범위를 제안합니다.

     

    const 키워드

    • 변하지 않는 값, 곧 상수(constant)를 정의할 때에는 const를 이용합니다. 
    • 값의 재할당이 불가능합니다. 값을 재할당할 경우 TypeError를 내므로, 의도하지 않은 값의 변경을 막을 수 있습니다.
    • let 키워드와 동일하게 블록 스코프를 따릅니다.

     

    • window객체 : 브라우저에만 존재함,var로 선언된 전역 변수 및 전역 함수는 window객체에 속하게 됨
    • 함수 선언식으로 함수를 선언하거나, var로 전역 변수를 만들면, window 객체에서 동일한 값을 찾을 수 있음
    • 전역 변수에 너무 많은 변수를 선언하지 말것
    • 전역 변수: 어디서든 접근 가능한 변수
    • 편리한 대신 다른 함수 혹은 로직에 의해 의도되지 않은 변경이 발생-부수효과side effect 발생
    • 전역 변수를 최소화하는 것은 side effect를 줄이는 좋은 방법
    • let과 const를 주로 사용
    • var 키워드는 블록 스코프를 무시합니다. 또한 재선언을 해도 에러를 내지 않습니다.
    • 전역 변수를 var로 선언하는 것은 브라우저의 내장 기능을 사용하지 못하게 만들 수도 있습니다.
    • 선언 없이 변수를 할당하지 마세요. 선언 없이 변수를 할당하면, 해당 변수는 var로 선언한 전역 변수처럼 취급됩니다.

     

    Strict Mode는 브라우저가 보다 엄격하게 작동하도록 만들어줍니다. 

    앞서 언급한 것처럼 "선언 없는 변수 할당"의 경우도 Strict Mode는 에러로 판단합니다.

    Strict Mode를 적용하려면, js 파일 상단에 'use strict' 라고 입력하면 됩니다.

     

     

    A. var로 선언한 변수는 window 객체에 속한 변수, 즉 전역 변수가 됩니다.

    B. 전역 변수는 꼭 필요한 경우가 아니라면 자제하는 것이 좋습니다. var보다는 let, const를 적극 활용하는 것이 좋습니다.

    C. age = 90과 같이 선언 없이 할당한 변수도 마찬가지로 전역 변수로 취급됩니다.

    D. strict mode를 사용하면 ‘선언 없는 변수 할당’을 브라우저가 에러로 처리하기 때문에 side effect를 방지할 수 있습니다.

Designed by Tistory.