클로져 활용법

J/Javascript 2014. 3. 18. 15:14

function makerSize(size){

return function(){

document.body.style.fontSize = size + 'px';

};

}

var size12 = makerSize(12); var size14 = makerSize(14); var size16 = makerSize(16);

 

document.getElementById('size-12').onclick = size12;

document.getElementById('size-14').onclick = size14;

document.getElementById('size-16').onclick = size16;

 

<a href="#" id="size-12"> 12 </a>

<a href="#" id="size-14"> 14 </a>

<a href="#" id="size-16"> 16 </a>

 

클로져 : 두개의 이루어진 특별한 오브젝트이다.

첫 번째는 함수이고 두 번째는 그 함수가 만들어진 환경이다.

그 함수가 만들어진 환경을 함수가 만들어질 때 사용할 수 있었던 변수들로 이루어진다.

 

function makefunc(){

var name = "Mozilla";

function displayName(){

alert(name);

}

return displayName;

}

이 경우에는 displayName 함수와 "Mozilla" 문자열을 포함하는 클로져이다.

 

var counter = (function(){

var privateCounter = 0;

function changeBy(val){

privateCounter += val;

}

return { increment : function(){ changeBy(1); },

decrement : function(){ changeBy(-1); },

value : function(){ return privateCounter; } };

});

 

자주 하는 실수 : 클로져

<p id="help"> Help </p>

<p> E - mail : <input type='text' id='email' name='email'> </p>

<p> Name : <input type='text' id='name' name='name'> </p>

<p> Age : <input type='text' id='age' name='age'> </p>

 

function showHelp(help){

document.getElementById('help').innerHTML = help;

}

function setupHelp(){

var helpText = [{'id' : 'email', 'help' : 'e-mail'}, {'id' : 'name', 'help' : 'name'}, {'id' : 'age', 'help' : 'age'}];

for(var i=0; i<helpText.length; i++){

var item = helpText[i];

document.getElementById(item.id).onfocus = function(){ showHelp(item.Help); }

}

}

setupHelp();

 

이 코드는 제대로 실행되지 않는다.

이유는 onfocus 이벤트에 지정한 함수가 클로져라는 것이다.

이 클로져는 함수 본체와 setupHelp 함수의 스코프로 이루어져 있다.

세개의 클로져가 만들어졌지만 각 클로져는 하나의 환경을 공유한다.

반복문이 끝나고 onfocus 콜백이 실행될때, 콜백의 환경에서 item 변수는 (세개의 클로져가 공유한다.)

helpText  리스트의 마지막 요소를 가리키고 있을 것이다.

여러개의 클로져를 이용해서 문제를 해결 할 수 있다.

 

function showHelp(help){

document.getElementById('help').innerHTML = help;

}

function makeHelpCallback(help){

return function(){ showHelp(help); };

}

function setupHelp(){

for(var i=0; i<helpText.length; i++){

var item = helpText[i];

document.getElementById(item.id).onfocus = makeHelpCallback(item.help);

}

}

setupHelp();

 

성능 관련해서

클로져가 필요하지 않은 작업인데도 함수 안에 함수를 만드는 것은 스크립트 처리 속도와 메모리 사용량 모두에서 현명한 선택이 아니다.

예를 들면 새로운 오브젝트나 클래스를 만들 때 오브젝트 생성자에 메소드를 정의하는 것 보다 오브젝트의 프로토타입에 정의하는 것이 좋다.

오브젝트 생성자에 정의하게 되면 생성자가 불릴 때 마다 메소드가 새로 할당되기 때문이다.

 

function MyObject(name, message){

this.name = name;

this.message = message;

this.getName = function(){ return this.name; };

this.getMessage = function(){ return this.message; };

}

  ||

  V

function MyObject(name, message){

this.name = name;

this.message = message;

}

 

MyObject.prototype = {

getName : function(){

return this.name;

},

getMessage : function(){

return this.message;

}

};

 

or

 

function MyObject(name, message){

this.name = name;

this.message = message;

}

MyObject.prototype.getName = function(){ return this.name; };

MyObject.prototype.getMessage = function(){ return this.message; };

위의 두 예제는 상속된 속성은 모든 오브젝트에서 사용될 수 있고 메소드 정의가 오브젝트 생성될 때마다 일어나지 않는다.

* 글로벌 변수는 delete로 지울 수 없다.

ex) // global variable;

var a = 1; // Don't Delete is set

delete a; // false

a; // 1

// normal function;

function f(){} // Don't Delete is Set

delete f; // false

type of f; // "function"

// ressigning doesn't help;

f  = 1;

delete f; // false

f; // 1

명기된 속성은 지울 수 있다.

var obj = {x : 1};

obj.y = 2;

delete obj.x; //true

delete obj.y; // true

obj.x; // undefined

obj.y; // undefined

 

설정

트랙백

댓글