: 변수, 식별자를 참조(접근)할 수 있는 유효한 범위
JS는 함수 레벨 스코프
를 지원
하지만, ES6에서 let
, const
가 도입됨
let, const는 블록 레벨 스코프
를 지원
// 함수 레벨에서 var를 사용
var 전역 = 11;
function 함수(){
var 지역 = 99;
console.log(전역); // 11
console.log(지역); // 99
}
함수();
console.log(전역); // 11
console.log(지역); // 지역 is not defined
// var은 함수 레벨 스코프기 때문에 함수 안에서 선언했다면 함수 밖에선 사용 못 함
// 블록 레벨에서 var를 사용
var 전역 = 11;
if(true){
var 지역 = 99;
console.log(전역); // 11
console.log(지역); // 99
}
console.log(전역); // 11
console.log(지역); // 99
// var은 함수 레벨 스코프기 때문에 함수가 아닌 다른문(if, for, while, ...)에서는 전역으로 동작함
// 중첩 스코프는 가장 인접한 지역을 우선 참조
var func1 = function () {
var a = 3, b = 5;
var func2 = function () {
var b = 7, c = 11;
// 이 시점에서 a, b, c 각각의 값은? 1번
a += b + c;
// 이 시점에서 a, b, c 각각의 값은? 2번
};
// 이 시점에서 a, b, c 각각의 값은? 3번
func2();
// 이 시점에서 a, b, c 각각의 값은? 4번
};
1번 (드래그 하면 보임)
a = 3, b = 7, c = 11
2번 (드래그 하면 보임)
a = 21, b = 7, c = 11
3번 (드래그 하면 보임)
a = 3, b = 7, c = not defined
4번 (드래그 하면 보임)
a = 21, b = 5
📝참고) https://velog.io/@thdgusrbek/스코프-안에서-변수는-어떻게-값을-찾을까
상위 스코프가 무엇인지에 따라 결과값이 달라진다.
이를 결정하는 2가지 기준이 있다.
1. 동적 스코프
: 함수를 어디서 호출 했는지에 따라 함수의 상위 스코프를 결정
2. 렉시컬 스코프
: 함수를 어디서 정의 했는지에 따라 함수의 상위 스코프를 결정
언어에 따라 1, 2번 중 한 가지를 따른다.JavaScript
는 2번 렉시컬 스코프 따름 (대부분 언어에서 렉시컬 스코프를 따름)
// func1, func2 호출하면 출력된 값은?
var x = 1;
function func1() {
var x = 10;
func2();
}
function func2() {
console.log(x);
}
func1(); // 1번
func2(); // 2번
1번 (드래그 하면 보임)
: 1
2번 (드래그 하면 보임)
: 1
var x = 40; // 전역 변수
function func () {
y = 60; // 선언하지 않은 식별자
console.log(x + y);
}
func(); // 100
js엔진은 y
에 값을 할당하기 위해 변수인지 확인하려고 스코프 체인을 사용
하지만, 끝까지 나오지 않음.
그래서 에러가 발생해야 하지만 js엔진은 window.y
또는 var y
로 해석하고 프로퍼티를 동적으로 생성한다.
이 현상을 암묵적 전역(implicit global)
이라 함
특징은 변수 선언없이 단지 전역 객체의 프로퍼티로 추가되었기 때문에 호이스팅이 발생하지 않는다.
(호이스팅은 발생하는데 let, const처럼 됨 ☜ 이 말이 맞나??)
console.log(x); // undefined
console.log(y); // ReferenceError: y is not defined
var x = 40; // 전역 변수
function func () {
y = 60; // 선언하지 않은 식별자
console.log(x + y);
}
func(); // 100