스코프란 '변수가 스크립트 안의 어떤 곳에서 참조할 수 있는가'를 결정하는 개념이다.
- 함수의 바깥에서 선언한 변수 => 글로벌 변수
- 함수의 안에서 선언한 변수 => 로컬 변수
그러나 var 명령을 사용하지 않고 선언된 변수는 모두 글로벌 변수로 간주한다. 때문에 var 명령으로 정의된 변수는 정의한 장소에 따라 변수의 스코프가 정해진다. 즉 로컬 변수를 정의하려면 반드시 var 명령을 사용해야 한다.
위와 같은 이유로 괜한 혼란의 소지를 만들지 말고 모든 변수에 var를 붙인다.
로컬 변수의 유효범위는 어디까지인가?
var scope = 'Global variable';
function getValue(){
console.log(scope); //1
var scope = 'Local variable'; //2
return scope;
}
console.log(getValue());
console.log(scope);
Java Script에서의 변수는 '함수 전체에서 유효'하므로 1의 시점에서 이미 로컬 변수 scope가 유효하게 된다. 그러나 1의 시점에서는 아직 로컬 변수가 확보되기만 했을 뿐 var 명령은 실행되지 않았다. 즉 로컬 변수 scope의 내용은 미정의(undefined)인 셈이다. 이러한 동작을 변수의 호이스팅(hoisting)이라고 한다. JavaScript의 이러한 동작은 생각지도 못한 버그의 원인이 된다. 때문에 로컬 변수의 함수는 선두에 선언한다는 사실을 기억해야 한다.
가인수의 스코프 - 기본형과 참조형의 차이 주의하기
가인수란 '호출원으로부터 함수로 건네진 값을 받는 변수'를 말한다. 가인수는 기본적으로 로컬 변수로 처리된다.
// *글로벌 변수와 로컬 변수(기본형)
var value = 10;
function decrementValue(value){
value--;
return value;
}
console.log(decrementValue(100)); //99
console.log(value); //10
// *참조형
var value = [1,2,4,8,16]; //1
function deleteElement(value){ //2
value.pop(); // 마지막 요소를 삭제
return value;
}
console.log(deleteElement(value)); //3
console.log(value); //4
침조형이란 '값 그 자체가 아닌, 값을 보관한 메모리상의 장소(주소)만을 보관하고 있는 형식'이다. 그리고 참조형의 값을 주고받는 경우에는 건네지는 값 또한(값 그 자체가 아닌) 메모리상의 주소 뿐이다.(이러한 값의 인도 방법을 참조에 의한 호출이라고 한다.)
즉, 1에서 정의된 글로벌 변수 value와 2에서 정의된 가인수(로컬 변수)가 변수로서는 서로 별개지만, 3에서 글로벌 변수 value의 값이 가인수 value에 전달되었을 시점에서는 실제 참조하고 있는 메모리상의 주소를 건네주게 되어 결과적으로는 동일한 장소(주소)를 참조하게 된다. 따라서 deleteElement 함수 안에서 배열을 조작한 경우, 그 결과는 글로벌 변수 value에도 반영된다.
블록 레벨의 스코프는 존재하지 않는다.(ES2015 이전)
if(true){
var i = 5;
}
console.log(i); //5
JavaScript의 경우, 블록 레벨의 스코프가 존재하지 않아 블록에서 빠져 나온후에도 변수가 유효해 계속 사용할 수 있다.
블록 스코프에 대응한 let 명령(ES2015)
ES2015에서 추가된 let 명령은 블록 스코프에 대응한 변수를 선언한다.
if(true){
let i = 5;
}
console.log(i); // i is not defined
switch 블록에서의 let 선언은 주의가 필요하다. switch 명령은 조건 분기 전체로서 하나의 블록이다. 그러므로 case 구문의 단위로 변수를 let 선언하는 경우에는 에러가 발생한다.
switch(x){
case 0:
let value = 'x:0';
case 1:
let value = 'x:1'; // 변수명의 중복
}
이러한 경우에는 switch 블록 밖에서 처음부터 변수 value를 선언해두도록 한다.
함수 리터럴/function 생성자에서 스코프의 차이
함수 리터럴과 function 생성자는 둘 다 익명 함수를 정의하기 위한 기능을 제공하고 있지만, 실은 함수 안에서 이것들을 이용했을 경우 스코프의 해석이 서로 다르다.
var scope = 'Global Variable';
function checkScope(){
var scope = 'Local Variable';
var f_lit = function(){return scope};
console.log(f_lit()); //Local Variable
var f_con = new Function('return scope;');
console.log(f_con()); //Global Variable
}
checkScope();
함수 리터럴 f_lit도, Function 생성자 f_con도 함수 내부에서 정의하고 있다. 하지만 결과를 보면 Function 생성자에서는 글로벌 변수를 참조하고 있다. Function 생성자 안의 변수는 그 선언 장소에 상관없이 항상 글로벌 스코프로 간주한다.
출처 : 자바스크립트 마스터북
'Web > javascript' 카테고리의 다른 글
[자바스크립트] 자바스크립트 스터디 (0) | 2019.12.05 |
---|---|
[자바스크립트] 쿠키 굽기 (0) | 2019.11.26 |
[자바스크립트] 함수를 정의할 때 주의할 네 가지 (0) | 2019.08.09 |
[자바스크립트] Javascript를 사용하여 현재 페이지 새로 고침하기 (0) | 2018.08.01 |
[브라우저] 로컬스토리지, 세션 스토리지 , 캐시 (0) | 2018.07.27 |