Scope란?
: 무언가 제한된 범위를 잘 들어다보기 위해 사용되는 개념,
범위가 있어야 함수가 잘 작동하는지 확인할 수 있다
Achievement Goals
- JavaScript의 Scope의 의미와 적용 범위를 이해할 수 있다
- JavaScript의 Scope 주요 규칙을 이해할 수 있다
- 중첩 규칙
- block scope(block-level scope) vs. function scope(function-level scope)
- let, const, var의 차이
- 전역 변수와 전역 객체의 의미
Rule1: Scope: 변수 접근 규칙에 따른 유효범위
- 변수는 어떠한 환경 내에서만 사용 가능. 프로그래밍 언어는 각각의 변수 접근 규칙을 가짐.
- 변수와 그 값이, 어디서부터 어디까지 유효한지를 판단하는 범위
- 자바스크립트는 기본적으로, 함수가 선언되는 동시에 자신만의 Scope를 갖는다.
Rule1
- firstName 에 접근할 수 있는 범위가 Local Scope에 한정돼 있다.
- Scope는 중첩이 가능. 함수 안에 함수를 넣을 수 있다.
- Global Scope는 최상단의 Scope로, 전역변수는 어디서든 접근가능.
- 지역 변수는 함수 내에서 전역 변수보다 더 높은 우선순위를 가짐.
Rule2: Function Scope(var) vs. Block Scope(let, const)
Block: 중괄호로 시작하고, 끝나는 단위
let키워드: 그러나. Block 단위로 Scope를 구분했을때 예측하기 쉬운 코드를 작성할 수 있다.
var키워드: 자바스크립트는 기본적으로, 함수 단위로 자신만의 Scope를 가진다. (Old Style)
var greeting = 'Good Night'
result: Good Night Steve!
let greeting
ReferenceError!
변수를 접근할 수 없을 때 나는 에러는 ReferenceError이다.
const 키워드
값이 변하지 않는 변수. 상수.
let 키워드와 동일하게 Block Scope를 따름.
값을 재정의하면 TypeError가 발생한다.
let | const | var | |
유효범위 | Block Scope | Block Scope | Function Scope |
값 재정의 | 가능 | 불가능 | 가능 |
재선언 | 불가능 | 불가능 | 가능 |
재선언 테스트
var 키워드로 재선언시 문제가 없어보이지만, 보통 이런 경우는 버그이므로 let 키워드를 사용해 이를 방지할 수 있다.
Rule3: 전역 변수와 window 객체
window: 전역 범위를 대표하는 객체
Global Scoped에서 선언된 함수, var키워드로 선언된 변수는 window 객체와 연결된다.
단, let으로 선언된 변수는 window객체에 연결되지 않는다.
다른 자바스크립트를 함께 작업할때는
브라켓안에 let 선언(지역변수설정)하여 사용하면 안전하게 사용가능하다.
Rule4: 선언 없이 초기화된 전역 변수
절대, 선언 키워드(var, let, const) 없이 변수 초기화하지 않는다. -> error가 안 난다. 변수 선언을 하지 않으면, 어떤 scope에서든 전역변수가 되므로 위험하다. (non-strict mode)
이런 실수를 방지하려면? Strict Mode 를 사용한다.
-> error를 발견할 수 있다.
Lexical Scope란?
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
var name = 'nero';
log();
}
wrapper();
위 코드의 답은 zero입니다. 스코프는 함수를 선언할 때 생기기 때문에
log 안의 name은 wrapper 안의 지역변수 name이 아니라, 전역변수 name을 가리키고 있는 겁니다.
이런 것을 lexical scoping이라고 합니다.
함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)에 있는 변수를 계속 참조하게 됩니다. 위의 예시에서는 log 함수 안의 name 변수는 선언 시 가장 가까운 전역변수 name을 참조하게 됩니다. 따라서 wrapper 안에서 log를 호출해도 지역변수 name='nero'를 참조하는 게 아니라 그대로 전역변수 name의 값인 zero가 나오는겁니다.