Frontend/JavaScript
[생활코딩] JS문법(함수)- 클로저
blueprint-12
2022. 1. 12. 20:57
클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.
클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용된다.
function outter() {
//내부에 inner이라는 지역변수를 만들고 그 변수에 함수를 할당한 것으로 이해하면 쉽습니다.
function inner() {
const title = "coding everyBody";
alert(title);
}
inner();
}
outter();
- outter()함수는 외부함수이고 inner()함수는 내부함수이다.
function outter() {
//title은 outter의 지역변수이다.
const title = "coding everyBody";
function inner() {
alert(title);
}
inner();
}
outter();
- title 은 outter의 지역변수이다.
- inner()함수는 외부함수 outter()의 지역변수 title에 접근가능하다. ->내부함수가 외부함수의 지역변수에 접근가능하다. 이것을 바로 클로저라고합니다.
클로저는 내부함수와 밀접한 관계를 가지고 있는 주제이다.
- 위의 코드는 return 값으로 내부함수를 반환하고 있다. 우리는 그것을 inner라는 변수에 담아서 inner()함수를 실행하고 있다. 여기서 의문이 드는 것은 return의 의미는 바로 작업을 종료, 즉 outter()함수가 소멸했다는 뜻인데 어떻게 inner()함수가 외부함수인 outter의 지역변수 title에 접근할 수 있냐는 것이다.
- 이처럼 내부함수는 외부함수의 지역변수에 접근할 수 있는데 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 클로저라고 한다.
Private Variable
Private 속성은 객체의 외부에서는 접근 할 수 없는 외부에 감춰진 속성이나 메소드를 의미한다. 이를 통해서 객체의 내부에서만 사용해야 하는 값이 노출됨으로서 생길 수 있는 오류를 줄일 수 있다.
TIP: 함수의 매개변수는 함수 안에서 지역변수로 사용됩니다.
function factory_movie(title) {
//매개변수 title은 함수factory_movie()의 지역변수입니다.
return {
// 객체를 리턴
//get_title(), set_title()메소드를 가지고있음
get_title: function () {
return title;
},
set_title: function (_title) {
if (typeof _title === "string") {
title = _title;
} else {
alert("타이틀은 문자로 작성해야합니다. ");
}
},
};
}
ghost = factory_movie("Ghost in the shell");
matrix = factory_movie("Matrix");
alert(ghost.get_title()); //Ghost in the shell
alert(matrix.get_title()); //Matrix
ghost.set_title(1); //타이틀은 문자로 작성해야합니다.
ghost.set_title("공각기동대");
alert(ghost.get_title()); //공각기동대
alert(matrix.get_title()); //Matrix
- 위의 코드를 보면 객체를 리턴하고 있는 외부함수 factory_movie가 매개변수로 title을 받고 있다. 여기서 title은 외부함수의 지역변수로 사용된다. 리턴하고 있는 것이 객체이지만 객체에 메소드가 정의돼있기 때문에 내부함수로 생각하면 됩니다. 이 내부함수 get_title()은 반환값으로 외부함수의 title(factory_movie의 지역변수 title)을 사용하고 있습니다. set_title()메소드의 경우 매개변수로 _title을 받아서 그 값을 title에 담아 변경하고 있습니다. 이는 곧 _title 값을 외부함수의 지역변수 title에 담는다는 것입니다.
- 동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다.
- 같은 외부함수를 공유하고 있는 ghost와 matrix(객체를 담은 변수)의 get_title의 결과는 서로 다릅니다. -> 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체가 됩니다.
- 외부함수의 지역변수 title은 내부에 정의된 객체의 메소드에서만 접근 가능할 수 있는 값이다. 이 말은 title의 값을 읽고 수정 할 수 있는 것은 factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미다. ->클로저의 이러한 특성을 이용하여 Private한 속성을 사용할 수 있다.(원래는 JS에서 Private한 속성을 지원하지 않습니다.)
※이슈: 예제에서는 if문의 조건식을 "String"으로 대문자로 사용하셨지만 실제로 typeof _title을 해보면 string으로 나옵니다. 그냥 typeof _title === "String"을 하면 계속해서 else문이 실행되니 주의, String -> string (o)
🤢클로저의 활용
//변수선언을 var로 하게되면 오류가 나는 코드이지만
//const 와 let을 쓰면 원하는 결과가 나온다.
//원하는 결과: 0,1,2,3,4
//var 을 사용한 코드의 결과: 5가 5번 출력
// var const let 그리고 그냥 변수명만 있을 때의 특성을 알아두자
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function () {
return i;
};
}
for (var index in arr) {
console.log(arr[index]());
}
이 코드에 대해서는 제대로 이해하지 못했으므로 다시 보고 정리하도록 함