스코프 (scope)는 '범위'라는 뜻을 가지고 있다.
자바스크립트 뿐만 아니라 모든 프로그래밍 언어에서 스코프(scope) 란 말이 쓰이는데, 스코프는
스코프 : 변수또는 함수의 식별자가 사용되는 유효범위
라고 정의 할 수 있다.
let name = 'kim';
if (name) {
let message = `Hello, ${name}!`;
console.log(message);
}
console.log(message);
위 예시와 같은 코드가 있다고 했을 때, 자바스크립트에선 변수가 선언된 위치에 따라 어디에서는 변수 사용이 불가할 때가 있다.
위 코드의 출력 결과는 아래와 같다.
Hello, Kim!
ReferenceError //message 변수를 찾을 수 없습니다.
자바스크립트의 스코프 규칙에 따라
let
키워드로 선언된message
라는 변수는 변수가 선언된 코드 블럭{}
외부에서는 접근할 수 없기 때문에 Reference 에러를 출력하게 된다.
- name : if 코드블럭 바깥에서 선언되었기 때문에 코드 전체에 해당하는 스코프를 가진다.
- message : if 코드블럭 내부에서 선언되었기 때문에 if 문 안에서만 사용할 수 있다.
if 구문 뿐만 아닌 함수 function 블럭에서도 이러한 스코프에 구분은 생기게 되는데
let name = "lee";
function greeting () {
let hi = 'hello!'
console.log(hi + name);
}
console.log(hi);
위 코드의 출력 결과는 아래와 같다.
hello, lee!
ReferenceError //hi 변수를 찾을 수 없습니다.
이번에는 if구문이 아닌 함수 블럭에 의해 스코프에 구분이 생기게 되었고 함수스코프 내부에서 선언된 hi
라는 변수는 함수 외부에서 접근할 수 없게 되었다.
스코프 규칙을 잘 알아두어야 선언된 변수를 불러올 수 없어 생기는 reference 에러를 방지할 수 있고, 고정되어야 하는 변수가 함수 내에서 바뀌게 되는 것을 방지할 수 있다.
위에 스코프 예시들을 보고 유추할 수 있는 규칙이 있다.
1. 내부에서 정의된 변수는 외부 스코프에서 접근이 불가능하다.
2. 외부에서 정의된 변수는 내부 스코프에서 접근이 가능하다.
3. 지역 스코프는 전역 스코프보다 더 높은 우선순위를 가진다.
- 스코프는 부모와 자식 관계와 같이 중첩되어 있다.
- 가장 바깥의 스코프는 전역 스코프(Global scope)라고 부르고 그 외 구분된 내부의 스코프들은 지역 스코프(Local scope)라고 부른다.
3번 규칙이 매우 중요한데 다음과 같은 예시가 있다.
let name = "김씨";
function showName () {
let name = "이씨";
console.log(name);
}
console.log(name); //김씨
showName(); //이씨
console.log(name); //김씨
여기서 두개의 name
변수가 등장하는데 전역에있는 "김씨" 와 내부스코프에 있는 "이씨"가 있다.
- 첫번째 console.log : 전역에 있는
name
김씨를 출력.- 두번째 console.log :
showName()
함수가 실행되었기 때문에, 함수 내부에 console.log(name)을 실행 -> 지역 스코프의 name 이씨를 출력- 세번째 console.log : 첫번째와 마찬가지로 전역에 있는
name
을 출력;서로 다른 스코프에서 정의된 변수들은 그들의 변수명이 같더라도 엄연히 다른 변수 취급을 받는다.
스코프란 네임 스페이스(name space) 이다. _"자바스크립트 Deep Dive"
위 코드에서 함수스코프 내의 name 변수 앞 let
을 제거해주면
let name = "김씨";
function showName () {
name = "이씨";
console.log(name);
}
console.log(name); //김씨
showName(); //이씨
console.log(name); //이씨
이 경우 let 키워드가 없기 때문에 전역 변수로 존재하는 name
변수가 "이씨" 로 재할당 되었다. 하나의 name
변수만이 존재한다.
변수 뿐만 아니라 함수 또한 스코프를 따른다.
function foo() {
console.log('global function foo');
}
function bar() {
function foo() {
console.log('local function foo');
}
foo();
}
bar(); //local function foo
foo(); //global function foo
bar 함수 내에서 호출한 foo 함수는 해당 스코프 내에서 검색된 bar 내부의 foo 함수를 실행하며, 외부에서 호출한 foo 는 전역 스코프에 위치한 foo 함수를 실행한다.
렉시컬 스코프는 스코프 결정 방식 중 하나이다.
var x = 1;
function foo () {
var x = 10;
bar();
}
function bar() {
console.log(x);
}![](https://velog.velcdn.com/images/rlatp1409/post/e42881ac-b9c9-44c1-b3b0-67ad979fb9e5/image.png)
foo(); //1번
bar(); //2번
위와 같은 코드가 있을 때, bar에 수행 결과는 상위 스코프가 무었인지에 따라 결정되는데,
- 함수를 어디서 호출했는지? (동적 스코프)
=> bar의 호출임으로 foo내부의 bar는 10을, 외부에 bar는 1을 출력.- 함수를 어디서 정의했는지? (렉시컬 스코프 또는 정적 스코프)
=> bar의 선언임으로 foo내부의 bar도 1을, 외부에 bar도 1을 출력.
여기서 두가지의 스코프 결정방식 중 첫번째를 동적 스코프 라고 하고, 두번째를 렉시컬 스코프라고 한다. 동적 스코프는 함수가 호출된 시점에 따라 상위 스코프를 결정해야하기 때문에 동적으로 바뀌게 된다.
자바스크립트는 이 두가지 방법중 렉시컬 스코프를 따르고 있다.
렉시컬 스코프는 클로저함수와 깊은 연관이 있다.