93ee962ea10e584040cc592512236c94.jpg

[javascript] Scope

변수의 범위/영역.
함수를 호출 시, 그 함수가 실행되는 동안 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) = 지역변수
스크린샷 2019-11-03 오후 9.11.11.png

[javascript] Closure

클로저는 함수 실행 할 때가 아닌 정의 할 때 생성됨.
단순히 함수 외부의 변수에 접근 가능한 내부함수 일 뿐만 아니라 함수가 선언되는 그 순간, 함수가 실행될 때 실제 외부변수에 접근하기 위한 객체이고 정의된 함수에서 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
  • 스코프와 클로져가 헷갈린다면..

    함수 one의 scope는 그 함수의 body이고 함수 one의 클로져는 자신의 scope와 global scope접근 할 수 있게 함
    함수 two의 scope는 two의 body이고 two의 클로져는 그 자신과 one그리고 global scope에 접근할 수 있게 함
<하기 참고>
// 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()()();// 호출호출