자바스크립트를 포함한 모든 프로그래밍 언어의 기본적이며 중요한 개념!!
--> 스코프는 변수, 함수와 깊은 관련이 있다.
--> 식별자의 유효한 범위
--> 식별자를 검색할 때 사용하는 규칙
function add(x, y) {
console.log(x, y); // 2, 5 매개변수의 스코프는 함수 몸체 내부이다.
return x + y;
}
add(2,5);
console.log(x, y) // ReferenceError: x is not found, 매개변수는 함수 몸체 내부에서만 참조 가능
var x = 'global';
function foo() {
var x = 'local';
console.log(x); // local
}
foo();
console.log(x); // global
--> 이 예시에서 변수 x는 식별자 이름이 같지만, 스코프가 다른 별개의 변수이다.
--> 스코프는 파일의 폴더 같은 역할을 한다. 다른 스코프에서는 같은 식별자를 사용할 수 있음!!
var 키워드로 선언한 변수의 문제점
--> const, let 키워드로 선언한 변수와는 다르게, var 키워드로 선언한 변수는 같은 스코프 내에서 중복 선언이 가능하다. -> 재할당시키는 부작용이 발생
1) 전역(global): 코드의 가장 바깥 영역, 전역 스코프, 전역 변수
2) 지역(local): 함수 몸체 내부, 지역 스코프, 지역 변수
전역과 전역 스코프
var x = 'global x'; var y = 'global y'; function outer() { var z = 'outer's local z'; console.log(x); // global x console.log(y); // global y console.log(z); // outer's local z function inner() { var x = 'inner's local x'; console.log(x); // inner's local x console.log(y); // global y console.log(z); // outer's local z } inner(); } outer(); console.log(x); // global x console.log(z); // ReferenceError: z is not found
전역: 코드의 가장 바깥 영역
전역 변수는 어디서든지 참조할 수 있다.
지역과 지역 스코프
지역: 함수 몸체 내부
지역 변수: 자신의 지역 스코프와 하위 지역 스코프에서 유효
--> 함수는 중첩될 수 있으므로 함수의 지역 스코프도 중첩될 수 있다.
--> 스코프가 함수의 중첩에 의해 계층적 구조를 갖는다.
스코프가 계층적으로 연결된 것을 스코프 체인이라 한다.
* 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
스코프 체인의 물리적인 실체 --> 렉시컬 환경
스코프 체인에 의한 변수 검색
--> 자바스크립트 엔진은 스코프 체인을 따라 변수를 참조하는 코드의 스코프에서 시작해서 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
--> 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조할 수 있지만 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다. (단방향)
스코프 체인에 의한 함수 검색
--> 함수도 식별자이기 때문에 스코프를 갖는다. 변수 검색때와 마찬가지로 스코프 체인이 작동한다.
--> 코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성된다!! (if문 내부의 변수는 전역변수이다!!)
var x = 1;
if (true) {
var x = 10;
}
console.log(x); // 10 조건문 내부에서 선언된 x는 전역 변수이다.
--> var 키워드로 선언한 변수는 함수의 코드 블록만을 지역 스코프로 인정한다. -> 의도치 않은 재할당이 발생할 수 있다.
* 해결책: ES6에서는 let, const 키워드를 도입하였다. 두 키워드는 블록 레벨 스코프가 적용된다.
1) 동적 스코프: 함수가 호출되는 시점에 동적으로 상위 스코프를 결정
2) 렉시컬 스코프: 함수가 정의되는 시점에 상위 스코프가 정적으로 결정
--> 자바스크립트는 렉시컬 스코프를 따른다.
--> 함수가 호출된 곳은 전혀 영향을 미치지 않는다!!
var x = 1;
function foo() {
var x = 10; // 무시된다.
bar(); // bar 함수가 foo 함수 내부에서 호출된 것은 상관이 없다.
}
function bar() {
console.log(x);
} // bar 함수는 전역에서 선언된 함수이다 --> 전역 스코프를 상위 스코프로 사용
foo(); // 1
bar(); // 1