JS Closure

강정우·2022년 10월 6일
0

JavaScript

목록 보기
15/53
post-thumbnail

함수는 일급 객체(first-class object)

  • 일급 객체란, 다른 변수처럼 대상을 다룰 수 있는 것을 말한다.
  • 자바스크립트에서 함수는 일급 객체이다.
  • 즉, 자바스크립트에서 함수는 변수처럼 다룰 수 있다.
  • JS에는 전역으로 존재하는 Function이라는 객체가 있는데 그래서 우리가 만든 모든 함수들은 바로 이 function객체를 상속받는 인스턴스가 되는 것이었다. prototype chain 이라는 것 덕분에 Function 객체 밑에있는 bind, apply, call등의 함수에 접근할 수 있는 것 이다.
function add(a,b){
	return a+b
}

// 함수를 다른 함수의 인자로 넘긴다.
[1, 2, 3].reduce(add, 0)

(() => {
	console.log('익명 함수를 생성한다.')
})()

function outer(a){
	function inner(b){
    	return a+b
    }  // 중접함수를 생성한다.
    return inner(10)
}

const Person = (name) => {
	// 함수를 변수로 생성한다.
    const printName = () => console.log(name)
    return {printName}
}  // 함수를 리턴하며 closure를 생성한다.

const person = Person('Daniel')    
person.printName()

function printName(name){
	console.log('name :', name)
}

// 함수끼리 비교한다.
// ===의 경우, 변수가 같은 객체(함수)를 가르키는지 체크한다.
console.log(printName === person.printName)
  1. 함수자체를 다른 함수의 인자로 넘길 수 있다.
  2. 이름이 없는 익명함수를 생성할 수 있다.
  3. 함수를 변수처럼 생성할 수 있다.
  4. 함수를 변수처럼 같은지 비교 가능하다.

클로저(Closure)

  • JS의 closure는 함수의 일급 객체 성질을 이용한다.
  • 함수가 생성될 때, 함수 내부에서 사용되는 변수들이 외부에 존재하는 경우 그 변수들은 함수의 스코프에 저장된다.
  • 함수와 함수가 사용하는 변수들을 저장한 공간을 클로저(closure)라 한다. => 그 함수가 선언돼었을 때의 lexical 환경을 기억하고 있다.
  • 만약에 내부에 어떤 변수가 있을 때 JS는 그 변수를 closure 공간에 저장한다. 그래서 return된 함수와 그 변수가 생명을 같이 하도록 만든다.
  • 함수를 생성해서 return하는 함수를 Factory 함수라고 한다. 이때 팩토리함수 내부에서 생성된 변수가 있을 텐데 문제는 그 변수들이 팩토리함수가 끝났는데도 계속 메모리에 살아있다. 그래서 이런 변수들이 어디에 들어있을까 라는게 바로 closure에 의미이다.
function createCard() {
	let title = "";
    let content = "";
    function changeTitle(text) {title = text}
    function changeContent(text) {content = text}
    function print() { 
    	console.log("TITLE -", title);
        console.log("CONTENT -", content);
    }
    return {changeTitle, changeContent, print};
}
    
const card1 = createCard();

card1.changeTitle("생일카드");
card1.changeContent("생일 축하해");
card1.print();

const card2 = createCard();

card2.changeTitle("감사카드");
card2.changeContent("고마워");
card2.print();
  • createCard()는 card라는 closure를 생성하는 팩토리 함수이다.
  • 그리고 팩토리얼 함수는 마지막에 return할 때 사용된 모든 함수를 return하면 좋고 상황에 따라 뺄껀 빼면 더욱 좋다.
let rate = 1.05;

function app(){
	let base = 10;
    return function (price){
    	return price * rate + base;
    };
}

const getPrice = app();
getPrice(120)  //136
console.log(app()(1));  // 11.05
rate = 1.1;
console.log(app()(1));  // 11.1
  • base는 app 함수 내부, rate는 app 함수 내부의 스코프에 존재한다.
  • 함수가 참조하는 변수는 실행 시점에 실행 컨텍스트에 의해 스코프가 결정된다.
  • 스코프에 따라서 변수에 영향을 받는다.
  • rate의 변경은 두 클로저 함수 호출에 반영되지만, base는 증가해도 영향을 미치지 않는다.
  • base는 app 호출 시 매번 생성되는 반면, rate는 매번 생성되지 않는다.

활용

  1. 상태 유지 => 앞서 언급한 예제와 가장 비슷하며 factory 함수처럼 어떠한 함수를 return함으로써 return 당시의 상태를 기억하여 prop들의 상태를 유지해주는 것이다.

  2. 정보은닉 => private를 흉내낼 수 있는 방법으로 한마디로 setter 메서드를 생성하지 않음으로써 변수(prop) 값에 접근할 수 없도록 하는 방법이 있다.

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글