[JavaScript] 스코프(Scope)

Hannahhh·2022년 7월 11일
0

JavaScript

목록 보기
14/47

🔍 스코프(Scope)


👀 스코프의 정의와 주요 규칙

블록({}) 바깥 스코프에서 선언한 변수는 안쪽 스코프에서 사용 가능하지만, 블록({}) 안쪽 스코프에 선언한 변수는 바깥쪽 스코프에서 사용 불가능하기 때문에 Reference Error가 발생한다.


//Example1
let username = 'kimcoding';

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

console.log(message); // Reference Error

//Example2
let greeting = 'Hello';
function greetSomeone() {
  let firstName = 'Josh';
  return greeting + ' ' + firstName;
}

console.log(greetSomeone()); // 'Hello Josh'
console.log(firstName); // Reference Error

따라서, 변수가 선언된 위치(블록 안쪽 or 바깥쪽)가 중요하며 이러한 변수 접근 규칙에 따라 변수에 접근할 수 있는 범위가 존재한다. 이 범위를 스코프라고 부른다.


스코프는 중첩이 가능하며 가장 바깥쪽의 스코프를 전역 스코프(Global Scope), 그 외 안쪽의 스코프들은 지역 스코프(Local Scope)라고 부른다.

또한, 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.

//Example1
let name = '김코딩';    //전역 변수

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

console.log(name); // 김코딩(첫 번째 출력)
showName();        // 박해커(두 번째 출력)
console.log(name); // 김코딩(세 번째 출력)

첫 번째, 세 번째 출력의 경우 스코프 규칙에 의해 지역 변수에 접근할 수 없으므로, 전역 변수 name의 값을 출력한다.
두 번째 출력의 경우, 지역 변수 name의 이름이 전역 변수와 같지만, 우선순위가 더 높기 때문에 지역 변수 name이 출력된다. 이러한 현상을 '쉐도잉'이라고 부른다.


//Example2
let name = '김코딩';

function showName() {
  name = '박해커';
  console.log(name); // 두 번째 출력
}

console.log(name); // 김코딩(첫 번째 출력)
showName();        // 박해커(두 번째 출력)
console.log(name); // 김코딩(세 번째 출력)

앞의 예제와 다르게 지역변수 내에서 let 키워드를 이용해 변수를 선언하지 않고, 전역 변수 name을 재할당한 경우, showName 함수가 실행되기전에 동작한 첫 번째 출력의 경우 전역변수에서 할당한 값을 출력하고, 그 이후 두,세번째 출력에서는 name의 값을 재할당했기 때문에 재할당한 값이 출력된다.


✔ 정리

  1. 스코프는 변수 접근 규칙에 따른 유효범위를 의미한다.

  2. 안쪽 스코프에서 바깥쪽 스코프로 접근할 수 있지만 반대는 불가능하다.(첫 번째 규칙)

  3. 스코프는 중첩이 가능하다.(두 번째 규칙)

  4. 우선 순위: 지역변수 > 전역변수 (세 번째 규칙)



👀 스코프의 종류

지역 스코프는 함수 스코프, 블록 스코프 총 2가지 종류가 있다.

✔ 함수 스코프(Function Scope)

function 키워드가 등장하는 함수 선언식 및 함수 표현식으로 스코프를 만든다.(단, 화살표 함수는 블록 스코프로 취급된다.)

함수의 실행부터 종료까지의 범위를 가지며 함수 내에서 선언 키워드가 없는 선언은 함수의 실행 전까지 선언되지 않은 것으로 취급한다.


✔ 블록 스코프(Block Scope)

중괄호를 기준으로 범위가 구분된다. +화살표 함수

블록 스코프 안에서 정의된 변수는 블록 범위를 벗어나는 즉시 접근할 수 없다.

//Example1 : let을 이용해 변수 i 선언
for(let i =  0; i < 5; i++){
    console.log(i);           //다섯 번 반복
}

console.log('final i:', i );  // Reference Error



✔ 블록 스코프와 var 키워드

그러나, var 키워드는 블록 스코프를 무시하고 함수 스코프만 따르기 때문에 var 키워드를 사용해 변수를 선언하면 블록을 벗어나도 변수에 접근할 수 있다. (단, 화살표 함수의 블록스코프는 무시하지 않음)

//Example2 : var을 이용해 변수 i 선언
for(var i =  0; i < 5; i++){
    console.log(i);           //다섯 번 반복
}

console.log('final i:', i );  // final i: 5

코드 작성 시 블록은 들여쓰기가 적용되어 구분이 시각적으로 분명하기때문에 많은 사람들은 블록 스코프를 기준으로 코드를 작성하고 생각한다. 때문에, 규칙을 무시하는 var 키워드의 사용은 코드가 다소 혼란스러울 수 있으므로 let 키워드를 사용한 변수선언이 권장된다. 그러나 값을 재할당할 일이 없다면 let과 마찬가지로 블록스코프를 따르는 const 키워드를 사용한 변수선언이 권장된다. let과 다르게 재할당이 불가능하기 때문에 의도치 않은 값의 변경을 방지하여 보다 안전하다.



✔ let, var, const 키워드 비교


letconstvar
유효 범위블록 스코프 & 함수 스코프블록 스코프 & 함수 스코프함수 스코프
값 재할당가능불가능가능
재선언불가능불가능가능



✔ 변수 선언 시 주의점


Window 객체(브라우저 only)

var로 선언된 전역 변수 및 전역 함수는 window 객체에 속하게 된다.

전역변수 최소화

전역 변수를 많이 생성하는 것은 편리한 대신, 다른 함수 or 로직에 의해 의도치 않은 변경이 발생(side effect)할 수 있기 때문에 이를 방지하기 위해 전역 변수를 최소화하는 것이 좋다.

let, const를 주로 사용

var는 블록 스코프를 무시하며 재선언을 해도 에러를 내지 않기때문에 버그를 유발할 수 있으며, 전역변수를 var로 선언할 경우, 선언된 변수가 window기능을 덮어씌워서 내장 기능을 사용할 수 없게 만들 수도 있다.

선언 없는 변수 할당 금지

선원 키워드없이 변수를 할당할 시, 변수가 var로 선언한 전역변수처럼 취급된다. strict Mode('use strict';)를 적용하면 브라우저가 엄격하게 작동하도록 만들어주기 때문에 이러한 실수를 방지할 수 있다.



Reference: 코드스테이츠

0개의 댓글