클로저를 이해하기 전, 알아야 될 내용이 많다,,
클로저만 봤다가 몇시간을 헤맨지 모르겠다 ㅎ
• 실행 컨텍스트와 스코프 체인
메인은 클로저니까 간단하게만 이해해보자.
- 실행 컨텍스트(Execution Context)
우리가 작성한 코드가 실행되는 환경으로,
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
- 글로벌 실행 컨텍스트(Global Execution Context)
코드가 실행되기 전 생성되는 것(전역 실행 컨텍스트)
모든 스크립트 코드는 전역 실행 컨텍스트 안에서 실행됨
프로그램에 단 한개만 존재하고, 실행 컨텍스트의 기본 - 함수 실행 컨텍스트 (Function Execution Context)
전역 실행 컨텍스트가 생성된 후, 함수가 실행될 때마다 새로운 실행 컨텍스트가 작성됨
함수 내에 존재하는 코드로, 함수가 실행될 때마다 만들어지는 실행 컨텍스트
- 스코프 체인
해당 코드의 유효 범위 안에 있는 변수를 정의하는 객체의 체인
JS는 변수 값을 얻으려 할 때 스코프 체인에서 변수를 찾음
(첫 번째 객체에서 찾아보고 없으면 두번째 객체, 세번째 객체 ..)
- 실행 컨텍스트에서 스코프 체인 작동 방법
실행 컨텍스트는 LIFO 스택 구조
var v = "전역 변수";
function a() {
//function a Execution Context(EC)
var v = "지역 변수";
function b() {
//function b Execution Context
console.log(v);
}
b();
}
//Global Execution Context
a();
위의 코드는 아래 그림과 같은 순서로 동작한다.
글로벌 실행 컨텍스트(GEC)가 먼저 스택에 쌓인다.
그 다음, 함수 호출 순으로 실행 컨텍스트 스택에 쌓이고
가장 늦게 호출된 함수 b가 실행 컨텍스트 안에서부터 탐색을 시작한다.
함수 b가 변수 v를 탐색하는데, 실행 컨텍스트 스택에 쌓여있는 순서로 탐색을 한다.
(b() Context 탐색 후 없다? -> a() Context 탐색)
scope chain은 기본적으로 이렇게 작동한다.
• 클로저
- 클로저란?
- 어떤 함수가 자신의 내부가 아닌 외부에서 선언된 변수에 접근하는 것
- 함수와 함수가 선언된 어휘적(Lexical) 환경의 조합
=> 함수의 유효범위는 함수가 어디서 실행됐냐가 아닌 어디서 정의되었는지에 따라 달라짐(Lexical scope)
클로저를 이해하기 위해 Lexical scoping 규칙을 알아야한다.
JavaScript는 Lexcial scope를 따른다는데 Lexical scope가 뭘까?
Lexcial scope란 함수가 정의된 시점의 스코프 체인을 사용하여 함수가 실행된다는 것이다.
함수가 호출된 시점이 아니라 정의된 시점이라는 것이 포인트이다.
function hello() {
var text = 'Hello ';
function say(name) {
return text + name;
}
return say;
}
var a = hello();
a("heedonguri"); // Hello heedonguri
hello 함수는 이미 호출된 상태이므로 hello 함수 내의 정의된 지역변수 text는 사라질 것이라고 생각할 수 있다.
하지만 a("heedonguri")를 실행했을때, hello 함수의 지역변수였던 text 변수가 참조되어 'Hello'를 리턴하고 있다.
이것이 Lexical scoping 규칙에 의한 클로저의 특성이다.
함수는 호출된 시점이 아니라, 정의된 시점의 스코프 체인을 사용하기 때문에 가능하다.
say 함수가 정의된 스코프 체인에서, text 변수는 'Hello'로 바인딩 되었고,
hello가 어디서 호출되든 상관없이 hello가 실행될 때 이 바인딩은 유효하다.
hello가 실행될 때, 지역변수인 text가 바인딩된 객체가 만들어지고, 이 객체가 스코프 체인에 추가된다.
hello가 반환됐을 때, 이 객체 또한 사라져야 하지만,
hello 함수 내부의 say 함수가 반환되어 변수 a에 저장되었으므로, hello 함수에 대한 참조가 남아 있어 스코프 체인이 남아있다.
- 결론
클로저는 반환된 내부함수가 자신이 선언되었을때의 환경(Lexical environment)인 스코프를 기억하여,
자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경에 접근할 수 있는 함수
=> 자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수다!!
• 클로저 함수의 장점
- 데이터를 보존할 수 있음
외부 함수의 실행이 끝나더라도 외부 함수 내의 변수를 사용가능
특정 데이터를 스코프안에 가두어 둔 채로 계속 사용할 수 있도록 해줌
- 정보 은닉과 캡슐화
객체 지향 프로그래밍에서의 public과 private와 같은 개념
a = (function() {
var privateFn = function() {
alert('hello');
}
return {
publicFn : function() {
privateFn();
}
}
})();
a 내부의 publicFn은 privateFn을 호출
publicFn의 scope에는 privateFn이 없지만, 클로저에서 접근할 수 있기 때문에 호출 가능
privateFn을 직접 호출 X, 공개된 publicFn을 통해서 호출 가능
이렇게 공개할 것과 공개하지 않을 것을 정할 수 있고, 이를 통해 정보은닉과 캡슐화가 가능함
- 모듈화
함수 하나를 독립적인 부품의 형태로 분리하는 것을 모듈화라고 함 -> 함수의 재사용성을 극대화
클로저 함수를 각각의 변수에 할당하면, 각자 독립적으로 값을 보존하고 사용가능
클로저를 통해 데이터와 메소드를 묶을 수 있음
'JavaScript' 카테고리의 다른 글
[JS] 유효성 검사 (0) | 2023.12.30 |
---|---|
[JS]JavaScript 화살표 함수 (0) | 2023.05.29 |
JavaScript this (0) | 2023.05.28 |
JavaScript 동작원리 (0) | 2023.05.27 |
JavaScript DOM (0) | 2023.05.16 |