변수의 범위/영역.
함수를 호출 시, 그 함수가 실행되는 동안 Scope만들게 됨.
그리고 함수가 끝나면 Scope는 사라지는 데 동일 함수를 두 번 호출하면, 두 번째가 실행되는 동안 새로운 다른 Scope를 생성하고 그 후에 두 번째 Scope도 사라짐.
function printA() {
console.log(answer);
let answer = 1;
};
printA();
printA();
//상위 2개의 Scope는 서로 다름. 그리고 변수 answer는 서로 공유되지 x
모든 함수의 Scope는 생명주기를 가지고 있고 그들은 생성된 후 바로 버려짐.
Nested scopes
함수가 다른 함수 내부에서 정의되었다면, 내부 함수는 외부 함수의 변수에 접근할 수 있고 이런 "행동"을 렉시컬 스코핑(lexical scoping)이라고 함.
외부 함수는 내부 함수의 변수에 접근할 수 없다.
cf> 렉시컬 스코프(Lexical scope) = 지역변수
클로저는 함수 실행 할 때가 아닌 정의 할 때 생성됨.
단순히 함수 외부의 변수에 접근 가능한 내부함수 일 뿐만 아니라 함수가 선언되는 그 순간, 함수가 실행될 때 실제 외부변수에 접근하기 위한 객체이고 정의된 함수에서 scope/global scope그리고 그 사이의 모든 nested scope를 포함한다.
그리고 스코프(scope) 를 응용한 함수라고 볼 수 있다.
클로저를 이용해 구현하게 되면 스코프를 이용해 접근하기 때문에 this라는 키워드를 쓸 필요가 없다. 하기의 counter는 어느 객체에 붙여서 사용해도 동일한 결과를 낸다.
객체 지향의 "은닉화"측면에서 본다면 객체보다는 클로저에서 더 극대화된다.
원래 JS의 모든 객체는 프로퍼티들의 외부 접근이 모두 허용되는 데 하기 count라는 변수는 외부에서 접근할 방법이 전혀 없다.
function counterFactory() {
let count = 0;
return function bb() {
count += 1;
return count;
};
}
let counter = counterFactory();
let counter2 = counterFactory();
console.log("첫번째", counter()); //'첫번째' 1
console.log("한번 더",counter()); //'한번 더' 2
console.log("카운터2======>",counter2());//'카운터2======>' 1
let app = {
counter: counter
};
let app2 = {
counter2: counter2
};
console.log(app.counter()); // 3
console.log(app.counter()); // 4
console.log("========>", app2.counter2()); //'========>' 2
<하기 참고>
// scope : global
let a =1;
function one (){
//scope : one
//closure : [one, global]
let b =2;
console.log ("함수안 1번째", a, b, a+b);//'함수안 1번째' 1 2 3
return function two (){
//scope : two
//closure : [two, one, global]
let c =3;
console.log ("함수안 2번쨰", a+b+c);//'함수안 2번쨰' 6
return function three (){
//scope : three
//closure :[three, two, one, global]
let d = 4;
console.log ("함수안 마지막", a+b+c+d);//'함수안 마지막' 10
}
}
}
one()()();// 호출호출
```