변수에 접근할 수 있는 범위
💡 이름이 같은 변수가 중복 선언 되었을 때, 어떤 변수를 참조할 것 인지에 대한 규칙 중괄호나 함수를 사용해서 블록을 만들어 준다.
[출처: https://velog.io/@dbfudgudals/scope-closure]
⚡ 주의 ⚡
하지만 자바스크립트는 특별한 시작점이 없으며 코드가 나타나는 즉시 해석되고 실행된다. 따라서 전역에 변수를 선언하기 쉬우며 이것는 전역 변수를 남발하게 하는 문제를 야기시킨다.
전역 변수의 사용은 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만드므로 사용을 억제하여야 한다.
출처: https://velog.io/@dbfudgudals/scope-closure
자바스크립트는 함수 레벨 스코프(function-level scope)를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1
let y = 0;
{
let y = 1;
console.log(y); // 1
}
console.log(y); // 0
전역변수 X와 지역변수 X가 중복 선언 되었다.
전역 영역에서는 전역변수만이 참조 가능하고, 함수 내 지역 영역에서는 전역과 지역 변수 모두 참조 가능하나 위와 같이 변수명이 중복된 경우, 지역변수를 우선하여 참조한다.
렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다. 자바스크립트는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다. 함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다.
var x = 10; **//** **전역 변수**
function foo () {
**//** **선언하지 않은 식별자**
y = 20;
console.log(x + y);
}
foo(); **// 30**
선언하지 않은 변수임에도 불구하고, 참조되어 값을 출력한다. 선언하지 않은 식별자에 값을 할당하면 전역객체의 '프로퍼티' 가 된다.
이때 foo 함수의 스코프와 전역 스코프 어디에서도 변수 y의 선언을 찾을 수 없으므로 참조 에러가 발생해야 하지만 자바스크립트 엔진은 y = 20
을 window.y = 20
으로 해석하여 프로퍼티를 동적 생성한다. 결국 y는 전역 객체의 프로퍼티가 되어 마치 전역 변수처럼 동작한다. 이러한 현상을 암묵적 전역(implicit global)이라 한다.
⚡주의⚡
하지만 변수 선언없이 단지 전역 객체의 프로퍼티로 추가되었을 뿐이기 때문에 변수가 아니고, 변수가 아닌 y는 변수 호이스팅이 발생하지 않는다.
변수가 아니라 단지 프로퍼티인 y는 delete 연산자로 삭제할 수 있다. 전역 변수는 프로퍼티이지만 delete 연산자로 삭제할 수 없다.
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name);
(function () {
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name);
}());
console.log(MYAPP.student.name);