[책펌] 자바스크립트 클로저(closure)에 대하여

By | 1월 7, 2014

- 출처: 이펙티브 자바스크립트(인사이트), 자바스크립트 핵심 가이드(한빛미디어) -
 
* 클로저란?

- 자신을 내포하는 함수의 문맥(context)에 접근할 수 있는 함수.
- 함수 자신이 포함하는 스코프의 변수들을 추적하는 함수.

 
* 클로저의 특징

- 외부함수의 실행 스코프가 종료된 상황에서도, 외부함수의 지역변수를 클로저가 참조하고 있다면,
해당 변수의 사본이 아닌 참조 자체를 클로저가 접근하여 값을 변경할 수 있다.
이 때, 외부함수의 지역변수는 클로저에 의해 마치 전역변수처럼 사용될 수 있다.

 
* 언제 클로저를 사용하나? (뭐가 더 있나 고민중 -_-..)

- 전역변수를 사용하지 않으면서도, private하면서 전역적인 값을 운용하고 싶을 때.
(함수에 지역변수를 정의하고 그 변수를 사용하는 클로저를 리턴하면, 클로저에서만 해당 값을 변경 가능)

 
* 클로저 샘플 01 - (외부함수의 매개변수에 접근)

function sandwichMaker(magicIngredient){
    return function(filling){
        return magicIngredient + " and " + filling;
    }
}
var hamAnd = sandwichMaker("ham");
hamAnd("cheese"); // "ham and cheese"
hamAnd("mustard"); // "ham and mustard"

 
* 클로저 샘플 02 - (외부함수의 지역변수에 접근, 클로저 3개)

function box(){
    var val = undefined;
    return {
        set: function(newVal){ val = newVal; }
        get: function(){ return val; }
        type: function(){ return typeof val; }
    }
}
var b = box();
b.type(); // "undefined"
b.set(98.6);
b.get(); // 98.6
b.type(); //"number"

 
* 클로저 샘플 03 - (외부함수의 지역변수에 접근)

//DOM 노드의 색을 노란색으로 지정하고 흰색으로 사라지게 하는 함수 정의
var fade = function(node){
    var level = 1;
    var step = function(){
        var hex = level.toString(16); //헥사코드 변환
        node.style.backgroundColor = '#ffff' + hex + hex;
        if(level < 15){
            level += 1;
            setTimeout(step, 100);
        }
    };
    setTimeout(step, 100);
};
fade(document.body);

 
* 클로저 샘플 04-1 (클로저를 인지하지 못한 잘못된 코딩)

function wrapElements(a){
	var result = [], i, n;
	for(i=0, n=a.length; i<n; i++){
		result[i] = function(){ return a[i]; }
	}
	return result;
}
var wrapped = wrapElements([10,20,30,40,50]); //이 코드 실행 직후 클로저가 참조하고 있는 i는 5이다.
var f = wrapped[0];
f(); // undefined (10이 나오면 정상)

 
* 클로저 샘플 04-2 (IIFE(즉시실행함수)로 지역스코프를 생성하여 클로저 실수 회피)

function wrapElements2(a){
	var result = [], i, n;
	for(i=0, n=a.length; i<n; i++){
		(function(){
			var j = i;
			result[i] = function(){ return a[j]; }
		})();
	}
	return result;
}
var wrapped2 = wrapElements2([10,20,30,40,50]);
var f2 = wrapped2[0];
f2(); // 10

 
* 클로저 샘플 04-3 (인수를 받는 IIFE를 사용한 클로저 실수 회피)

function wrapElements3(a){
	var result = [], i, n;
	for(i=0, n=a.length; i<n; i++){
		(function(j){
			result[i] = function(){ return a[j]; }
		})(i);
	}
	return result;
}
var wrapped3 = wrapElements3([10,20,30,40,50]);
var f3 = wrapped3[0];
f3(); // 10

※ IIFE 사용시 주의할 점
- IIFE가 루프 내에 있을 경우 break나 continue를 사용할 수 없다.
- IIFE 내부에서 this나 arguments를 참조할 경우 원하는 값을 얻을 수 없다.
 

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments