[Effective JavaScript] 클로저에 익숙해지자

김범식·2023년 6월 19일
0

Effective JavaScript

목록 보기
15/33
post-thumbnail

클로저는 이를 지원하지 않는 언어를 사용하다 넘어온 프로그래머에 게는 친근하지 않은 개념일 수 있지만 크롤저를 마스터하기 위한 노력은 분명 도움이 될것이다.




1. 자바스크립트는 현재 함수 외부에서 선언된 변수를 참조할 수 있다.

function makeSandwich(){
	var magicIngredient = "peanut butter";
		function make(filling){
			return magicIngredient + "and"+ filling;
		}
		return make("jelly");
}

makeSandwich(); //peanut butter and jelly

내부의 make 함수가 바깥에서 선언된, makeSandwich 함수에서 선언된magicIngredient 변수를 참조했다는 사실을 주목해야한다.



2. 함수는 외부 함수가 무언가를 리턴한 이후에도 이 외부함수에 선언된 변수를 참조할 수 있다.

자바스크립트는 1급객체이다. 이는 내부함수를 리턴할 수 있고, 이함수가 나중에 다시 호출될 수 있다는 뜻이다.

function snadwichMaker(){
	var magicingredient = "peanut butter";
		function make(filling){
			return magicIngredient + "and"+ filling;
		}
		return make;
}

var f = sandwichMaker(); //make함수 전달
f("jelly") // "peanut butter and jelly"
f("banana") // "peanut butter and banana"
f("marshmallows") // "peanut butter and marshmallows"

make 함수를 리턴한다는것 말고는 위의 코드와 동일하다. make함수return 되어 변수 f에 저장되어있더라도 magicingredient 변수의 값을 기억하고 있다.




이떻게 이런일이 가능할까? 자바스크립 함수는 해당 스코프에서 선언되어 참조할 수 있는 어떤 변수더라도 내부적으로 보관한다. 함수 자신이 포함하는 스코프의 변수들을 추적하는 함수르 클로저라고 한다.




magicingredientfilling 두개의 변수가 클로저에 저장되어있기 때문에 참조할 수 있다.

function sandwichMaker(magicIngredient){
	function make(filling){
		return magicIngredient + " and " + filling;
	}
	return make;
}

var hamAnd = sandwichMaker("ham");
hamAnd("cheese") // "ham and cheese"
hamAnd("mustard") // "ham and mustard"

var turkeyAnd = sandwichMaker("turkey");
turkeyAnd("Swiss"); // "turekey and Swiss"
turkeyAnd("Provolone"); // "turekey and Provolone"

같은 sandwichMaker 함수에서 나왔지만 다른 magicIngredient 변수를 클로저에 저장해 둔다. 즉 둘은 서로다른 객체이다. 클래스가 서로다른 객체를 만들어 내듯 서로다른 함수를 만들어 내는것 같다.




이처럼 클로저는 많은 유용한 코딩 관례들의 중심이 된다. 클로저를 생성하기 위한 더 편리하고 일반적인 문법을제공하는데, 함수 표현식이 바로 그것이다.

function sandwichMaker(magicingredient){
	return function(filling){
		return magicIngredient + " and "+ filling;
	}
}

이 함수는 지역적으로 호출하기위해 만들어진게 아닌 새로운 함수 값을 만들어 내기위한 용도이기 때문에 이름을 지을 필요가없다.



3. 클로저가 외부 변수의 값을 변경할 수 있다.

function box(){
	var val = undefined;
	return {
		set:function(newVal){val = newVal;},
		get:function(){return val;},
		type:function(newVal){return typeof val;}
	}
}

var b = box();
b.type(); // "undefined"
b.set(98.6);
b.get() //98.6
b.type() // "number"

var a = box();
a.get() // undefined. 

이 예제는 세개의 클로저 즉 set, get, type 프로퍼티들을 포함하는 객체를 생성한다.

ab는 서로다른 객체이기 때문에 영향을 주고 받지 않는다. 내부 클로저 함수들은 모두 같은 값을 공유하지만 a 와 b는 전혀 다른 값을 공유한다.



기억할 점

  • 함수는 외부 스코프에 선언된 변수를 참조할 수 있다.
  • 클로저는 자신을 생성한 함수보다 더 오래 지속된다.
  • 클로저는 내부적으로 외부 변수에 대한 참조를 저장하고, 저장된 변수를 읽고 갱신할 수 있다.
profile
frontend developer

0개의 댓글