유효범위(scope)는 변수가 선언되고 사용되는 맥락(context)을 말한다.
전역범위(global scope)에서 변수는 코드블럭의 바깥쪽에서 선언된다. 이러한 변수를 전역변수(global variable) 라고 부른다. 전역변수는 코드블럭을 포함한 프로그램의 모든 곳에서 접근할 수 있다.
코드 블럭 범위 (block scope)안에서 정의된 변수는 그 블럭 안에서만 사용가능하기 때문에 지역 변수(local variable) 라고 부른다.
아래의 예시를 보며 이해해보자.
let vsope = ‘global’;
function fscope( ) {
let vsope = ‘local’;
alert(scope);
}
fscope(); //결과 local 이라는 경고창 출력된다.
기본적으로 선언된 변수의 값을 찾을때 프로그램은 사용된 곳에서 가장 가까운 곳 부터 시작해서 먼곳까지 찾는다. 위의 함수에서 변수가 재정의된 코드가 없을때는 결과는 global이 출력되는데 그 이유는 함수안에서 변수를 찾지 못했기 때문에 바깥쪽의 변수를 이용한 것이다. 하지만 함수 안에서 변수를 재정의한 값 'local'이 있기 때문에 함수의 실행 결과 local이 출력 된다.
이런 개념들을
지역변수
(local variables),전역변수
(global variable)라고 한다. 블럭안에 정의된 변수가 지역변수, 블럭 밖에서 정의된 변수를 전역변수다. 지역변수는 블럭 안에서만 접근 할 수 있는 변수이고 자바스크립트 전역에서 접근 가능한 변수를 의미한다.
아래 예시를 보면 블럭안에서 정의된 변수값을 블럭 밖에서 찾으려고 할 때 undefined 라는 빈값이 결과로 출력되는걸 알 수 있다.
let vsope = ‘global’;
function fscope(){
let vsope = ‘local’;
let lv = ‘local variables’
alert(lv);
}
fscope(); //결과 local variables 경고창 출력
alert(lv); // undefined 경고창 출력
중요한 점은 지역변수의 유효범위는 함수 안이고, 전역변수의 유효범위는 프로그램 전역인데, 같은 이름의 지역변수와 전역변수가 동시에 정의되어 있다면 지역변수가 우선한다. 아래 예제를 보자. 결과는 모두 local이다.
let vscope = 'global';
function fscope(){
vscope = 'local';
alert('함수안'+vscope);
}
fscope();
alert('함수밖'+vscope);
함수밖에서도 vscope의 값이 local인 이유는 무엇일까? 그것은 함수 fscope의 지역변수를 선언할 때 let를 사용하지 않았기 때문이다. let를 사용하지 않은 지역변수는 전역변수가 된다. 따라서 3행은 전역변수의 값을 local로 변경하게 된 것이다. let 을 쓰는 것과 쓰지 않는 것의 차이를 이해해야 한다.
변수를 언제 어디서든 접근 가능하게 만드는게 좋아보일 수 있다. 하지만 이건 프로그램에 문제를 야기할 수 있다는점에서 절대 현명한 방법이 아니다. 지역변수와 전역변수중에 어떤걸 사용해야할지 분명하게 모르고 있을때는 반드시 지역변수를 사용해야한다.
프로그래밍이란 간단한것부터 복잡하게 발전하게 되어있기 때문에
수많은 함수들과 변수들이 만들어지는데 이때 무분별하게 자바스크립트 전체에 적용되는 변수를 지정해버리면 예상치못한 에러가 발생하는 등 프로그램이 의도와 달라질 수 있다.
프로그램의 에러를 방지하기 위해 변수를 선언할 때는 반드시 블럭 안에서 지역변수를 선언해 유효범위를 최대한 타이트하게 지정하는것이다.
유효범위를 타이트하게 지정하는 것은 다음같은 장점이 있다.
유효범위를 효과적으로 지정하는 좋은 예는 다음 같은 방식을 쓸 수 있다.
const logSkyColor = () => {
const dusk = true;
let color = 'blue';
if (dusk) {
let color = 'pink';
console.log(color); // pink
}
console.log(color); // blue
};
console.log(color); // ReferenceError
logSkyColor라는 전체를 감싸는 큰 함수를 만들고 내부에 조건문을 이용해서 color라는 변수값이 달라지게 했다. 그리고 함수 밖에서 color를 출력해보면 빈값으로, 전역변수를 사용하지 않았다는걸 알 수 있다.
함수에 이름을 정의하지 않은 것을 익명함수라고 한다. 이 방식은 자바스크립트에서 로직을 모듈화 하는 일반적인 방법이다.
( function () {
var MYAPP = {
MYAPP.calculator = {
'left' : null,
'right' : null
}
MYAPP.coordinate = {
'left' : null,
'right' : null
}
}
MYAPP.calculator.left = 10;
MYAPP.calculator.right = 20;
function sum(){
return MYAPP.calculator.left +
MYAPP.calculator.right;
}
document.write(sum());
}() )
익명함수의 사용방법은 함수의 끝에 호출을 의미하는 ( )를 입력하고 전체 함수 블럭을 ( )로 감싸주는 것이다.
자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는데, 이런 유효범위 방식을 정적 유효범위 (static scoping) 혹은 렉시컬 유효범위(lexical scoping)이라고 한다.
var i = 5;
function a() {
var i = 10;
b();
}
function b(){
document.write(i);
}
a(); //결과 5
다음을 보면 알 수 있듯이 함수 a 안에 b라는 함수가 실행되었지만 변수의 값은 a함수 안에서의 지역변수가 아니라 b 함수가 처음에 정의된 곳 기준으로 하여 전역변수값 5를 가졌다.
그 이유는 함수가 정의된 시점을 기준으로 변수의 범위를 갖기 때문이다.
유효범위의 개념은 디렉토리 개념과 비슷하다.
파일들이 늘어남에따라 같은 이름인 파일들은 덮어씌어지는 문제가 발생한다. 이걸 해결하기 위해 디렉토리를 생성하고 그 안에 파일들을 집어넣는 식으로 문제를 해결하게 되었다.
여기서 디렉토리가 코드 블럭, 그 안의 파일이름들이 지역변수를 의미로 이해할 수 있겠다.
참고자료:
생활코딩
codecademy