스코프의 종류

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

하나는 블록 스코프(block scope)라고 부르며, 중괄호(블록)를 기준으로 범위가 구분된다.

(두번째 예제의 변수 i는 중괄호 안에서만 사용할 수 있다)

또다른 스코프 종류로는 함수 스코프(function scope)가 있다.
function키워드가 등장하는 함수 선언식함수 표현식은 함수 스코프를 만든다.

여기서 한가지 유의해야 할 점이 있다.
화살표 함수블록 스코프로 취급된다.
함수 스코프가 아니다.

function키워드를 사용하면 함수 스코프이다.
이는 화살표 함수와 일반 함수의 가장 큰 차이점이다!!

함수 스코프블록 스코프는 논리적인 구분 외에도 코드를 작성할 때 기억해야 할 다른 점이 몇 가지 존재한다.
지금은 그냥 이 둘은 차이가 있다는 정도로만 기억해 두자.


블록 스코프(Block scope)

먼저 블록 스코프의 규칙에 대해 알아보자.

블록 스코프 안에서 정의된 변수 i는 블록 범위를 벗어나는 즉시 접근할 수 없다.
따라서 바깥에서 console.log(i)를 실행시켜보면 ReferenceError가 나오게 된다.

이번엔 위의 코드에서 변수 선언을 let 대신 var를 이용해본다.

어떻게 블록을 벗어났음에도 불구하고 변수 i에 접근할 수 있었을까?
결론부터 말하면, var키워드는 for문이 만들어낸 블록 스코프를 무시한다.

var 키워드와 let 키워드

변수를 정의하는 또다른 키워드 var

var키워드로 정의한 변수는 블록 스코프를 무시하고, 함수 스코프만 따른다.
그러나 모든 블록 스코프를 무시하는건 아니고, 화살표 함수의 블록스코프는 무시하지 않는다!!

함수 스코프는 함수의 실행부터 종료까지이고, var선언은 함수 스코프의 최상단에 선언된다.
선언 키워드 없는 선언은 최고 스코프에 선언된다.
함수 내에서 선언 키워드 없는 선언은, 함수의 실행 전까지 선언되지 않은 것으로 취급함.

보통 코드를 작성할 때 블록은 들여쓰기가 적용되고, 그 구분이 시각적으로 분명하기 때문에, 많은 사람들은 블록 스코프를 기준으로 코드를 작성하고 생각하기 마련이다.

그러나 var는 이 규칙을 무시하므로, 코드를 작성하는 사람이 블록스코프와 함수스코프에 대한 이해가 없으면 코드가 다소 혼란스러울 수 있다.

따라서, var보다는 let 으로 변수 선언을 하는 것을 권장한다!


var 키워드보다 let 키워드가 더 안전한 이유

우선 var 키워드는 재선언을 해도 아무런 에러가 나지않지만, let 키워드는 재선언을 방지한다.


위의 코드처럼
let 키워드는 재선언을 방지한다.
실제로 코딩할 때에 변수를 재선언해야 할 필요가 있을까??
대부분 이런 경우는 버그이다.


const 키워드

let키워드와 동일하게, 블록 스코프를 따른다.

값의 변경을 최소화하여 보다 안전한 프로그램을 만들 수 있다.
값을 새롭게 할당할 일이 없다면, const 키워드의 사용이 권장된다.

값을 재할당할 경우, TypeError를 낸다.


let , var , const 키워드 비교


개발자 콘솔로 var키워드와 let키워드를 비교해보기

우선 콘솔에 var키워드let키워드를 사용하여 비교해본다.

var키워드를 사용한 코드는 블록스코프를 무시하기때문에 함수 스코프 내부의 블록스코프를 무시하여 greeting변수가 사용되었다.
let 키워드를 사용한 코드는 블록스코프를 따르기 때문에
ReferenceError가 나왔다.

이번엔 Visual Studio Code에 코드를 쓰고 콘솔창에 열어 소스탭을 클릭하여 7번째 줄을 클릭하여 중단점(breakpoint)를 지정하고, 새로고침을 해보면 7번째 줄에서 break가 걸리고 스코프(Scope)창을 통해 두 종류의 스코프(Local Scope, Global Scope)를 확인이 가능하다.

Local Scope에는 (this 값을 제외하고)
세 개의 변수가 담겨있다.(firstName, greeting, time)
함수 안에 정의된 모든 변수를 Local Scope에서 사용가능.


이번엔 var키워드 대신 let을 사용하여 비교해보자.

Local Scope에 greeting변수가 없으므로, 7번째 줄에서 ReferenceError가 발생한다.

greeting변수는, 해당 block안쪽에서만 접근이 가능하다.


스코프와 관련해 변수 선언에서 주의할 점

스코프와 관련해 변수 선언에서 주의할 점을 알아보자.

window 객체(브라우저 only)

먼저 브라우저에만 존재하는 window객체에 대해 알아보자.

개발자 도구를 열어 콘솔에 window라고 입력해보면 객체 하나를 조회할수 있다.
이 객체는 사실 브라우저의 창(window)을 의미하는 객체이지만, 이와 별개로 전역 영역을 담고 있기도 하다.

함수 선언식으로 함수를 선언하거나, var로 전역 변수를 만들면, window 객체에서도 동일한 값을 찾을 수가 있다.

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

브라우저에는 window라는 객체가 존재.

window 객체

  • 브라우저 창을 대표하는 객체
  • 그러나, 브라우저 창과 관계없이 전역 항목도 담고 있음

var로 선언된 전역 변수와 전역 함수가 window객체에 속함

전역 변수는 최소화 하자.

전역 변수는 가장 바깥 스코프에 정의한 변수이다.
따라서, 어디서든 접근이 가능하다.

얼핏 '모든 변수를 바깥으로 빼면 스코프 걱정을 하지 않아도 되겠네?'
라는 생각이 들 수도 있지만 그러나, 전역 변수를 많이 만드는 것은
좋지않은 선택이다.

보통 애플리케이션을 만들 때에는, 내가 직접 작성하지 않은 수많은 다른 함수와 로직이 포함된다.
너도나도 똑같은 이름으로 전역 변수를 선언하려고 한다면 분명 문제가 발생할 것이다.

이를 side effect라고 한다.
전역 변수를 최소화하는 것은 side effect를 줄이는 좋은 방법이다.

앞서 배웠듯, var 키워드는 블록 스코프를 무시한다.
또한 재선언을 해도 에러를 내지 않는다.
그러므로 let키워드와 const키워드를 주로 사용할 것을 권장한다.

전역 변수를 var로 선언하는 것은 브라우저 내장 기능을 사용하지 못하게 만들 수도 있다.


선언 없이 변수를 할당하지 말자.

선언 없이 변수를 할당하면, 해당 변수는 var로 선언한 전역 변수처럼 취급된다.

Strict Mode

Strict Mode는 브라우저가 보다 엄격하게 작동하도록 만들어준다.
앞서 언급한 것처럼 '선언 없는 변수 할당'의 경우도 Strict Mode는 에러로 판단해준다.

Strict Mode를 적용하려면, 코드 상단에 'use strict'라고 입력하면 된다.(따옴표 포함)


profile
개발 재밌다

0개의 댓글