Javascript - 스코프

Hyunjun Jang·2021년 12월 18일
0

스코프란?

함수를 작성할 때 아래와 같이 중괄호 '{ }'를 이용하여 함수의 범위를 작성한다.
변수가 영향을 미치는 범위, 변수의 유효 범위 ,코드가 유효한 범위 라고 할 수 있는 규칙의 집합이다.
스코프의 종류에 따라 변수, 함수등의 유효 범위가 달라질 수 있다.
자바스크립트(ES6)는 크게 2가지 스코프 규칙이 있다.

레벨

자바스크립트는 전통적으로 함수 레벨 스코프를 지원해왔고, 얼마 전까지만 해도 블록 레벨 스코프는 지원하지 않았다. 하지만 ES6(ECMAScript 6)부터 블록 레벨 스코프를 지원하기 시작했다.

1. 함수 레벨 스코프
자바스크립트에서 var키워드로 선언된 변수나, 함수 선언식으로 만들어진 함수는 함수 레벨 스코프를 갖는다. 즉, 함수 내부 전체에서 유효한 식별자가 된다.

아래 코드는 아무런 문제없이 blue를 출력한다.

function foo() {
    if (true) {
        var color = 'blue';
    }
    console.log(color); // blue
}
foo();

만약 var color가 블록 레벨 스코프였다면, color는 if문이 끝날 때 파괴되고 console.log에서 잘못된 참조로 에러가 발생할 것이다. 그렇지만 color는 함수 레벨의 스코프이기 때문에 foo 함수 내부 어디에서든 에러 발생 없이 참조할 수 있다.

let color를 if블록 내부에서 선언하였다. 때문에 if블록 내부에서 참조할 수 있으며, 그 밖의 영역에서 잘못된 참조로 에러가 발생한다.

2. 블록 레벨 스코프
ES6의 let, const키워드는 블록 레벨 스코프 변수를 만들어 준다.
블록이 유효 범위이다.

function foo() {
    if (true) {
        let color = 'blue';
        console.log(color); // blue
    }
    console.log(color); // ReferenceError: color is not defined
}
foo();

let color를 if블록 내부에서 선언하였다. 때문에 if블록 내부에서 참조할 수 있으며, 그 밖의 영역에서 잘못된 참조로 에러가 발생한다.

var vs let, const
ES6가 표준화되면서, 블록 레벨과 함수 레벨을 모두 지원하게 되었다. "You don't know JS" 시리즈의 저자인 Kyle Simpson은 var, let, const가 서로 다르기에 필요한 상황에 알맞게 사용할 줄 알아야 한다고 설명하고 있다.

그렇지만 요즈음 ES6 코드 대부분은 var를 사용하지 않는다. var는 let과 const로 모두 대체가 가능하고, var자체가 함수 레벨의 스코프를 가지기 때문에 블록 레벨 스코프보다 더 많은 혼란을 야기하기 때문이다.

동작

렉시컬 스코프(Lexical scope)는 보통 동적 스코프(Dynamic scope)와 많이 비교한다.

1. 동적 스코프
동적 스코프는 프로그램의 런타임 도중의 실행 컨텍스트나 호출 컨텍스트에 의해 결정 된다.

var sister = '여동생';
function home() {
	var sister = '여동생 집에없다';
	getSister();
}
function getSister() {
	console.log(sister); // 여동생 집에없다
}
home();

함수를 호출할 때가 아니라 선언할 때 스코프가 정해지고 외부 변수는 내부 변수에 접근할 수 없기 때문에 not defined이 된다.

2. 렉시컬 스코프 (정적 스코프(Static scope) 또는 수사적 스코프(Rhetorical scope))
렉시컬 스코프에서는 소스코드가 작성된 그 문맥에서 결정된다. 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정한다.
현대 프로그래밍에서 대부분의 언어들은 렉시컬 스코프 규칙을 따르고 있다.

var sister = '여동생 숙제 중';
function home() {
  var sister = '여동생 집에없다';
  getSister();
}
function getSister() {
  console.log(sister); // 여동생 숙제 중
}
home();

Refence

https://meetup.toast.com/posts/86
https://okayoon.tistory.com/entry/%EC%8A%A4%EC%BD%94%ED%94%84Scope%EB%9E%80

profile
Let's grow together😊

0개의 댓글