변수, 함수와 깊은 관련이 있는 유효범위를 뜻하는 말
모든 식별자는 선언될 때 자신이 선언된 위치에 의해 참조할 수 있는 유효범위가 결정된다.
JS엔진은 식별자를 검색할 때 스코프라는 규칙을 통해 식별자를 결정한다. 같은 이름을 가진 식별자라도 스코프에 따라 구별될 수 있다. 같은 이름의 파일이 한 폴더에 있으면 안되지만 다른 폴더에 있다면 괜찮은 것과 같다.
전역변수는 제일 밖에 있는 변수로 어떠한 블록도 없는 곳에 선언한 변수이다.
지역변수는 함수 내에서 선언한 변수이다.
함수 내부에서 전역변수와 같은 이름의 지역변수를 선언한 후 그 변수를 참조하면 지역변수가 참조된다. 이유는 JS엔진이 스코프 체인을 통해 참조할 변수를 검색하고 같은 이름 임에도 지역변수가 먼저 참조되기 때문이다.
스코프 체인이란?
-> 물리적으로 존재하는 연결 체인이며 이를 통해 JS엔진은 하위부터 상위로 이동하며 식별자를 검색한다. 지역 스코프가 먼저 검색되는 이유는 하위부터 검색하기 때문이다.
오직 함수블록 내에서만 선언된 변수를 지역 스코프(함수 레벨 스코프)로 인정한다. 단 var키워드 변수만 그렇다. let과 const 키워드는 if나 for문 등의 다른 블록에서도 지역 스코프로 인정된다. var로 if문에서 변수를 선언하면 전역변수처럼 사용할 수 있게 된다. 이는 치명적이므로 의도한 것이 아니라면 let이나 const를 주로 사용해야한다.
var x = 1;
function foo(){
var x = 10;
bar();
}
function bar(){
console.log(x);
}
foo(); //x->10 or 1 ???
과연 JS엔진은 함수의 호출 위치에 따른 스코프(동적 스코프)를 채택했을까? 아니면 함수의 정의 위치에 따른 스코프(렉시컬 스코프)를 채택했을까?
위의 코드에서 foo를 호출하면 나오는 x의 값은 1이다. 따라서 JS엔진은 정의 위치에 따른 스코프를 채택한 것을 알 수 있다.
변수는 생물처럼 존재했다가 소멸하는 생명주기가 있다. 만일 변수가 소멸하지 않는다면 메모리는 꽉차게 된다.
전역 변수는 애플리케이션이 살아있는 경우 계속 살아있다. 서버를 돌리게 된다면 전역 변수로 선언한 변수는 서버가 꺼질 때까지 메모리에 살아있는 것이다. 변수의 생명주기는 메모리 공간 확보-> 메모리 공간 해제-> 가용메모리 pool에 반환이다.
변수 호이스팅은 스코프 규칙에 맞게 적용된다.
//예시
var x = 0;
function foo(){
console.log(x); // undefined 전역변수 x가 있어도 스코프 때문에 0이 출력되지 않는다.
var x = 10;
}
순서는 전역변수선언 -> 전역변수할당 -> 함수 호출 -> 지역변수선언 -> 지역변수할당 이다.
이 객체는 특별한 객체이다. 소스코드가 실행되는 런타임 이전에 제일 먼저 생성되는 특수한 객체이다.
클라이언트 단에서는 window, 서버 단에서는 global 객체를 의미한다.
이 전역 객체의 프로퍼티는 표준 빌트인 객체 (Object, String, Number ...), 환격에 따른 호스트 객체(클라이언트는 WebAPI, 서버는 Nodejs의 호스트API), 전역 변수, 전역 함수 등이 있다.
그래서 window.전역변수이름을 사용할 수 있다.
var Counter = (function(){ // 즉시 실행 함수로 반환값을 Counter에 할당한다.
// private 변수
var num = 0; // 그 이유는 반환값으로 num을 반환한다면 public이겠지만 그렇지 않다면 Counter를 통해서도 num에 접근할 수 없기때문에 private이다.
return { // private을 보호하기위해 보통 객체를 반환한다. 지역 변수를 반환하지 않는다.
increase(){
return ++num;
},
decrease(){
return --num;
}
};
}());
아까도 말했듯이 var로 선언한 변수는 여러가지 문제점들이 있다.
ES6부터 도입된 이 키워드는 여러 장점이 있다.
let x = 1;
{
console.log(x); // RefferenceError이다. 그 이유는 지역변수로 아래에 새로운 x를 선언했기 때문에 JS엔진은 새로운 x가 할당되지 않은 채인 것을 확인하고 에러를 낸다. 전역변수는 지역변수보다 나중에 확인되기 때문에 초기화가 되어있어도 console.log로 찍을 수가 없다.
//근데 실제로 f12를 눌러서 console창에서 찍어보니 SyntaxError가 나온다...이미 사용중인 변수인데 같은 변수를 또 선언하려고 한다는 에러이다...
let x = 2;
}
주로 사용해야할 키워드이다. 그 이유는 다음과 같다.
변하지 않는 상수를 가장 많이 사용하도록 하고 변수를 사용할 때는 let을 사용하되 꼭 이용해야하는 경우에만 변수를 사용하는 것이 좋다. 의도적으로 호이스팅이나 중복을 만들고 싶은 경우에는 var를 사용해도 되지만 되도록 않하는 것이 좋다.