toggle-toggle / javascript-basic

🌱우아한 테크코스 프론트엔드 자바스크립트 기초 스터디 입니다.
9 stars 0 forks source link

[2021.03.25] 클로저 #12

Open shinsehantan opened 3 years ago

shinsehantan commented 3 years ago

클로저란?

function outer() {
    let name = 'shinsehantan'

  return function inner() {
    alert(name);
     }
}

let inner = outer(); // 외부함수 실행하여 inner라는 변수에 담음.

inner();
// inner 실행 - alert를 띄워야 함. 
// alert에는 name이 필요.name은 outer 함수에 있음.

// outer 함수가 이미 return과 함께 생을 마감했고, 실행 컨택스트 스택에서도 제거되었지만
// outer 함수의 렉시컬 환경은 딱히 건드리지 않음. 

// 그래서 inner가 태어날 때 참조하기로 결정된, name에 접근할 수 있음
// inner는 클로저! 클로저에 의해 참조된 변수 name은 자유변수!

 // alert('신세한탄')은 정상적으로 동작!

어떻게 그렇게 되지? 스코프?

가비지 컬렉터?

function makeFunc() {
  let name = "shinsehantan";

  function printAlert() {
    alert(name);
  }

  return printAlert;
}

let myFunc = makeFunc(); 

// myFunc라는 변수에 printAlert이 리턴되어 담김.
// makeFucn 내부의 printAlert 함수는 makeFunc의 name인 shinsehantan을 참조하고 있었음.
// makeFunc이 실행되어 끝났고, 그래서 그 내부에 선언된 변수도 생명을 잃을 것 같아 보이지만!
// 참조하는 주체가 남아있기 때문에 이 유효범위의 어휘적 환경이 유지됨.

myFunc(); 

// myFunc 함수 실행 = 리턴된 printAlert 함수를 실행
// 필요한 name 변수에 접근 가능!
// 결과는 alert로 shinsehantan이 잘 뜸!
✔️✔️✔️✔️ test 1 ✔️✔️✔️✔️

let result = [];

for (let i = 0; i < 5; i++) {
  result.push(function () {
    return i
  })
}

console.log(result[1]()) 
// result = [0,1,2,3,4]일테니, result[1] === 1 일까? ㅇㅇ

console.log(result[3]())
// result = [0,1,2,3,4]일테니, result[3] === 3 일까? ㅇㅇ
✔️✔️✔️✔️ test 2 ✔️✔️✔️✔️

var result = [];

for (var i = 0; i < 5; i++) {
  result.push(function () {
    return i
  })
}

console.log(result[1]()) 
// result[1] === 1 일까? ㄴㄴ 5임

console.log(result[3]())
// result[3] === 3 일까? ㄴㄴ 5임

// 콜백함수는 콜스택이 모두 비워진 다음에 이벤트루프에 의해 콜스택으로 푸시됨.
// for문이 모두 돌았을 때, i는 이미 4?5?인 상태
// 콜백함수는 실행되지 않은 상태로 전역변수 i를 참조하고 있는 상태
// 이때 콜백함수가 실행되면 참조하고있던 전역변수 5를 사용하게 됨.

언제 쓰나?

출처