본문으로 바로가기

MooTools 의 bind 와 클로저(Closure)

By 양군, 2008-10-24

MooTools 를 사용하다보면 bind 라는 말이 종종 등장하고 documents 를 보다봐도 인자로 bind 가 자주 등장합니다. 처음 MooTools 를 접해 사용하면 이 bind 의 개념을 잡지 못해 헷갈리곤 합니다. 저도 첨엔 그랬습니다. 이 글에서는 이 bind 에 대해 가능한 최대한 아는대로 설명해 보겠습니다.

그리고, 이 글은 방명록에 펑크테디 님께서 남겨주신 질문에 대한 답이기도 합니다.

bind

MooTools 의 주요 함수들에 함수가 인자로 넘어갈때는 대부분 bind 인자가 함께 따라오는데요, 그 bind 인자에 대해 이렇게 설명하고 있습니다.

bind – (object) The object that the “this” of the function will refer to.

즉, bind 인자는 “해당 함수에서 this 로 참조할 객체” 정도 되겠네요. 예를 하나 보겠습니다.

// 사랑을 고백할 Lover 객체를 만듭니다.
// 인자로 넘어온 lover 가 해당 객체의 this.lover 에 저장됩니다.
var Lover = function(lover) {
	this.lover = lover;
};
// 고백할 함수를 추가합니다.
// 인자로 넘어온 who 에게 this.lover 가 고백 하는 함수입니다.
Lover.prototype.confess = function(who) {
	alert(this.lover + ' loves ' + who);
};
// 사랑을 고백할 gun이를 만듭니다. gun 의 this.lover 는 '건이' 가 될겁니다.
var gun = new Lover('건이');
// 이제 MooTools 의 Array.each 를 사용해 엄마, 아빠에게 고백합니다.
// 함수 인자로는 익명의 Lover 의 confess를 전달합니다.
// 이 new Lover().confess 에는 this.lover 가 없는 상태입니다.
// bind 인자로는 gun 을 할당합니다.
['아빠', '엄마'].each( new Lover().confess, gun );

마지막 인자로 넘어간 new Lover().confess 를 그냥 실행하면 누가 고백을 하는지 모를겁니다. new Lover() 의 this.lover에 아무 값도 할당 하지 않았으니까요. 하지만 두번째 bind 인자로 gun 을 넘겨서 new Lover().confess 의 this.lover 는 gun의 this.lover 가 사용되서 다음과 같이 이쁘게 고백할겁니다.

건이 loves 아빠.
건이 loves 엄마.

앞에서 언급한 “해당 함수에서 this 로 참조할 객체” 를 다시 보자면, “new Lover().confess 함수에서 사용할 this 가 참조할 객체가 gun 이 되는것” 입니다. 즉, new Lover().confess 의 this.lover 가 gun 의 this.lover 인 ‘건이’ 가 되는 겁니다.

예가 좀 억지스럽긴 하지만 이런 모습은 주로 DOM 객체에 이벤트를 할당할 때 자주 보게 되는 모습입니다. 이정도 이해로도 MooTools 를 사용하는데는 지장이 없을거라고 생각합니다만 … 사실 MooTools 의 bind 는 javascript 의 closure 와 깊게 관련이 있습니다. 즉, 정확히 이해하기 위해서는 closure 에 대한 이해가 선행 되야 합니다.

클로저(Closure)

클로저(Closure) 에 대한 설명은 아래 문서 링크들로 대신 하겠습니다.
closure 에 대한 이해가 없으신 분들은 일독을 권합니다.

이해 하셨나요 ?

Closure & MooTools bind

그렇다면 MooTools 에서 클로저가 적용되는 부분을 보겠습니다.

// 새로운 클래스를 만듭니다.
// id 와 name 을 인자로 받습니다.
// ID 가 id 인 Element 를 클릭했을 때 name 을 출력합니다.
var Alert = new Class({
	initialize: function(id, name) {
		this.name = name;
		this.initButton(id);
	},
	initButton: function(id) {
		$(id).addEvent('click', function() { alert(this.name); });
	}
});
// DOM 이 준비되면
// id 가 button 인 element 를 클릭했을 때 '양군' 이 출력되도록합니다.
window.addEvent('domready', function(){
	new Alert('button', '양군');
});

어떻겠습니까 ? 위의 코드는 잘 동작할까요 ?
위의 코드는 원하는대로 동작하지 않습니다. 바로 addEvent 에 전달된 function() {alert(this.name);} 이 문제가 되는데요. 이 부분이 closure 가 됩니다.

우리가 원하는것은 alert(this.name); 이 Alert 내에서 쓰였으므로 this 가 Alert 이길 바라지만 실제 이 closure 가 평가되는 부분은 DOM Element 에서입니다. 그래서 실제로 수행하게 되면 this 는 Alert 가 아니라 $(‘button’)이 됩니다.

var Alert = new Class({
	initialize: function(id, name) {
		this.name = name;
		this.initButton(id);
	},
	initButton: function(id) {
		// this.get('id') 를 출력해 해당 element의 id를 출력하도록 변경.
		$(id).addEvent('click', function() { alert(this.get('id')); });
	}
});
window.addEvent('domready', function(){
	new Alert('button', '양군');
});

이렇게 수정해서 실행하면 ‘button’이 출력됩니다. alert(this.get(‘id’)); 에서 this 가 $(id) 가 되기 때문에 문제 없습니다. 그렇다면 처음의 코드를 어떻게 수정해야 원하는대로 동작할까요.

바로 MooTools 에서 제공하는 Function::bind 를 사용하면 됩니다. 수정된 코드는 아래와 같습니다.

var Alert = new Class({
	initialize: function(id, name) {
		this.name = name;
		this.initButton(id);
	},
	initButton: function(id) {
		// this 를 bind 로 넘겨 closure 를 생성합니다.
		$(id).addEvent('click', (function() { alert(this.name); }).bind(this));
	}
});
window.addEvent('domready', function(){
	new Alert('button', '양군');
});

Function::bind 는 해당 함수내에서 this 가 참조할 객체를 설정하면서 closure 를 생성합니다.
Function::bind 의 인자에 대한 설명입니다.

1. bind – (object, optional) The object that the “this” of the function will refer to.
2. args – (mixed, optional) The arguments to pass to the function (must be an array if passing more than one argument).

Conclusion

보시면 알겠지만 MooTools 의 bind 를 사용하는데 Closure 의 이해는 사실 필요 없습니다, 다만 필요한 인자의 타입이 함수인 경우에 Function::bind, Function::bindWithEvent, Function::pass 등의 함수를 이용해 함수를 만들어주면 됩니다. 그리고 bind 인자에 대한 이해 정도만 있으면 됩니다. 이는 closure에 대한 이해가 필요한 부분을 MooTools 가 내부에서 감쇠시키고 있기 때문입니다. 즉, 그런거 잘 몰라도 MooTools만 쓸 줄 알면 되도록 해주고 있는겁니다.

하지만, Closure 에 대한 이해가 선행된다면 MooTools 혹은 다른 JavaScript 라이브러리의 사용이 더욱 자유롭고 유연해질 수 있을거라고 믿습니다. 그리고 우리에게 언제나 MooTools를 사용할 수 있는 환경이 제공되지는 않을거라는 걸 잘 알고 있기 때문에라도 Closure에 대한 이해는 필요합니다.

May the force be with you.

관련 포스트

2 Responses

  1. 펑크테디 님의 말:

    정말 감사합니다. 엄청 자세하게 설명해주셨네요

    열심히 읽어보고 이해하는 일만 남았군요..

  2. 건이아빠 님의 말:

    펑크테디 님
    아닙니다. 마침 포스팅 꺼리도 없었는데 잘됐다 싶어 달렸봤습니다. ^^
    부디 도움이 되었길 바랍니다.

댓글을 달아주세요.

OfficeFolders theme by Themocracy. Modified by Yangkun (It's me). Valid XHTML 1.0 Transitional 올바른 CSS입니다!