스코프(Scope) 란?
스코프는 참조 대상 식별자(identifier: 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분해 식별할 수 있는 유일한 이름) 을 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다.
기본적으로 프로그래밍에서는 변수를 선언하고 값을 할당하며 변수를 참조할 수 있는 기능을 제공하게 되고
이를 토대로 프로그램의 상태를 관리할 수 있다.
전역 변수 혹은 코드 블록 (if, while, for, try/catch 등) 함수 내에 선언하여 변수는 중첩될 수 있고,
자신이 어느곳에서 선언되었는지에 따라서 코드가 자신을 참조할 수 있는 범위를 갖게 된다.
스코프(Scope)의 구분
자바스크립트에서는 총 2가지로 나누어져 있다.
- 전역 스코프 (Global Scope)
- 지역 스코프 (Local Scope)
전역 스코프
코드의 어느곳에서든 참조할 수 있는 범위이다.
이곳에 선언된 변수는 전역 변수(Global Variable)이 되며 코드 어디에서든 참조가 가능하다.
let x = 'global';
function foo() {
console.log(x); // 전역 변수로 선언되니 아래에서도 참조가 가능하다.
}
foo(); // global
console.log(x); // global
지역 스코프
코드블록, 함수내에서의 범위이며 자기 자신과 하위 범위에서만 참조가 가능하다.
이곳에서 선언된 변수는 지역 변수(Local Variable)이 되며 해당 지역과 그 하위 지역에서만 참조가 가능하다.
let x = 'global';
function foo() {
let x = 'local';
console.log(x);
}
foo() // local;
console.log(x) // global
함수 레벨 스코프(Function-level scope)
자바 스크립트는 함수 레벨 스코프를 사용합니다.
그렇기 때문에, 함수 내에서 선언된 변수는 함수 외부에서는 유효하지 않습니다.
let a = 10; // 전역변수
function test() {
let b = 20; // 지역 변수
}
console.log(a) // 10
console.log(b) // 'b' is not defined
따라서 b는 test라는 함수의 지역 변수가 되기 때문에 위와 같은 결과가 나오게 됩니다
함수 내에 존재하는 내부 함수
다음의 예제를 통해 알아보도록 하겠습니다.
let x = 'global';
function foo() {
let x = 'local';
console.log(x); // local
function bar() {
// 내부함수
console.log(x) // 'local'
}
bar();
}
foo();
console.log(x) // 'global'
내부 함수는 자신을 포함하고 있는 외부함수의 변수에는 접근할 수 있습니다.
이러한 이유로 외부 함수의 변수값도 변경 가능하고 가장 인접한 지역을 우선으로 참조하게 됩니다.
let x = 10;
function foo() {
let x = 100;
console.log(x) // 100
function bar() { // 내부함수
x = 1000;
console.log(x); // 1000
}
bar();
}
foo();
console.log(x); // 10
또한 함수 내부에서 전역 변수를 참조할 수 있으므로 전역 변수의 값도 변경이 가능하다!
let x = 10;
function foo() {
x = 100; // 선언만 하더라도 위에 x 값을 참조할 수 있다.
console.log(x); // 100
}
foo();
console.log(x):
렉시컬 스코프
let x = 1;
function foo() {
let x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // ?
foo(); // ?
위 함수의 실행 결과는 과연 어떻게 될까?
결론을 말하자면 1이 두번 출력 된다.
왜 그렇게 될까?
자바스크립트는 렉시컬 스코프를 따르기 때문이다.
렉시컬 스코프는 함수를 어디에서나 호출하는지가 아니라 어디에서 선언하였는지에 따라 결정된다고 한다.
따라서 함수를 어디에서 호출하였는지 스코프 결졍에 아무런 의미를 주지 않게되고, bar함수는 전역에 선언되었기
때문에 전역 변수 x를 참조하게되어 1을 두번 출력하게 되는 것이다.
암묵적 전역 (implicit global)
let x = 10; // 전역 변수
function foo() {
// 선언하지 않은 식별자
y = 20;
console.log(x + y);
}
foo(); // ?
위 함수의 실행 결과는 어떻게 될까? 정답은 30이 출력된다.
"y"라는 변수가 선언되지 않고 사용되었다면 ReferenceError 가 뜨는게 정상아닌가?
전역 객체의 프로퍼티가 되기 떄문에 foo()라는 함수가 호출되면 자바스크립트 엔진은 y에 값을 할당하기 위해서
스코프 체인을 통해 선언된 변수인지 확인을 한다!. 근데 어느곳에서도 y라는 변수는 선언되지 않았으므로 참조
에러가 발생하는게 맞지만, 자바스크립트 엔진은 window.y로 해석하여 프로퍼티를 동적으로 생성한다.
따라서 y는 변수가 아닌 전역 객체(window)의 프로퍼티로 추가가 되었을 뿐이고, 변수 호이스팅은 발생하지 않는다고
한다!!
참고 자료
'프론트 엔드 > Javascript' 카테고리의 다른 글
[Javscript] 구조분해할당 활용하기 (0) | 2022.01.16 |
---|---|
[Javascript] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) 차이 (0) | 2022.01.16 |
[Javascript] 호이스팅 이란? (0) | 2022.01.16 |