반응형
Block Scope
- 함수 스코프는 함수의 인해서 생기는 범위, 변수의 유효범위를 뜻하지만 블록 스코프(Block Scope)는 블락 '{}' 에 인해서 생기는 유효범위라고 말할 수 있다.
- 즉 { }에 인해서 변수의 유효범위가 결정된다.
{}의 범위
{
let a = 10
{
let a = 20
console.log(a)
}
console.log(a)
}
console.log(a)
- 위의 결과를 보면 첫 번째와 두 번째 a의 값은 정의되어있다는 것을 알 수 있다. 즉 첫 번째와 두 번째로 a를 호출한 범위가 {} 블록 안에서 있기 때문에 정의될 수 있다.
- 하지만 세 번째 a호출은 {}블락 범위 안에 있지 않고 외부에 있기 때문에 a가 정의되지 않아 에러가 발생한다. 이점이 ES5와 ES6+의 다른점이라고 볼 수 있다.
var와 let, const의 {}블록 범위
function hasValue (p) {
console.log(v)
if (p) {
var v = 'blue'
console.log(v)
} else {
var v = 'red'
console.log(v)
}
console.log(v)
}
hasValue(10)
- ES6+에서 {} 블록이라는 개념이 생겨도 var로 변수를 지정하면 원래 기능은 그대로 실현되도록 나두었다.
- 그래서 위의 코드 결과를 보면 마지막 v 호출이 {} 블록 밖에 있어도 blue라는 값이 호출된다.
function hasValue (p) {
console.log(v)
if (p) {
let v = 'blue'
console.log(v)
} else {
let v = 'red'
console.log(v)
}
console.log(v)
}
hasValue(10)
- 하지만 ES6+에서 나온 새로운 변수 let으로 하면 {} 블락 범위가 그대로 실행되어 마지막 v 호출은 {} 블락 범위 내에 없으므로 결과가 오류로 등장한다. const로 변수를 지정해도 똑같은 결과가 나온다.
- 즉 블록 스코프는 let과 const 라는 변수에서만 작동한다고 볼 수 있다.
블록 스코프와 HOISTING
if (true) {
let a = 10
if (true) {
console.log(a) // TDZ 존
const a = 20
}
console.log(a)
}
console.log(a)
- 자바스크립트 언어 중 값, 식, 문으로 나뉠 수 있는데 이때 문은 if문 for문 swich문이 있을 수 있다. 이때 블록{} 범위는 if문의 if(){}의 {} 또한 블록 범위로 적용된다는 것을 알아야 한다.
- 위 코드에서 만약 외부함수 if문안에 들어있는 if문 내부함수에서 호출한 a가 Hoisting이 된다면 a는 아직 a가 변수로 선언되지 않았기 때문에 undefined가 뜨고 Hoisting이 안된다면 a는 자기가 있는 지역 변수에 없다는 것을 외부함수에서 a 변수를 찾기에 a는 10이 등장할 것이다.
- 하지만 위의 결과는 레퍼런스 오류가 등장한다. 이것을 TDZ(Temporal Dead Zone 임시 사망 지역)이라고 불린다. 즉 {}블록 안에서 let, const로 변수를 지정하면 let, const 변수로 선언하기 전 위치에 오기전까지는 undefined을 할당하지 않고 바로 변수를 호출할 수 없다는 레퍼런스 오류가 나오는 규칙이 존재하는 것이다.
- 만약 옛날 버전인 var로 변수를 선언하였다면 레퍼런스 오류가 나오지 않고 그냥 undefined가 할당되어 실제 실무에서 눈치를 못챌 수도 있다.
- ES6+는 과거 ES5에서 변수 선언과 호출의 위치에 따라 오류가 발생하는 암묵적인 규칙을 없애기 위하여 이러한 규칙으로 보안하였다고 볼 수 있다.
this와 블록 스코프
var value = 0
var obj = {
value: 1,
setValue: function () {
this.value = 2; // 메소드 안에 들어있는 this는 메소드를 포함 시킨 obj다.
(function () {
this.value = 3 //이 this는 메소드안이 아니라 함수안에 들어있어 전역객체 window다.
대신 a.call(this)을 넣어주면 obj을 this로 쓸 수 있다.
})();
}
}
obj.setValue()
console.log(value)
console.log(obj.value)
위 코드와 같이 메소드가 아닌 함수 안의 this는 window 전역 객체를 가르킨다는 문제가 있어 번거롭다.
let value = 0
let obj = {
value : 1,
setValue : function () {
let a = 10;
this.value = 2
{
let a = 20;
this.value = 3
}
}
}
obj.setValue()
console.log(value)
console.log(obj.value)
하지만 블록 범위를 주면 블록 범위 안에있는 this는 자동으로 바로 위의 외부 함수의 this 범위를 가져와서 사용한다.
for 문과 블록 스코프
var sum = 0
for (let i = 1 ; i <= 10 ; i++) {
sum += i
}
console.log(sum)
console.log(i)
- 위의 코드 중 for문의 인자 중에 let i =1; 이라는 변수를 주었는데 이때 특별한 경우로 let i = 1;은 {}블록으로 감싸있지 않아도 저 for문 안에서만 유효범위를 갖는다.
- i를 호출한 것은 에러가 뜨는데 이는 let i 변수가 for문 안에서만 유효하다는 것을 알수 있는 거다.
반응형
'프로그래밍 개발 > JS ES6+' 카테고리의 다른 글
Javascript ES6+ rest parameter (나머지 매개변수) (0) | 2020.12.09 |
---|---|
Javascript ES6+ default parameter (매개변수 기본값) (0) | 2020.12.09 |
Javascript ES6+ template literal (0) | 2020.12.08 |
Javascript ES6+ forEach, map, reduce 메소드 (0) | 2020.12.08 |
Javascript ES6+ block scoped variables (0) | 2020.12.07 |
댓글