티스토리 뷰

Programming language/javascript

바인딩이란?

hello-world 2013. 2. 6. 11:50
728x90
반응형

바인딩이란 무엇인가~ 



bind : 결속시키다, 묶다 



특정객체에서 실행되게끔 고정시키는 그런 역활이라 할 수 있겠다.


즉 바인딩이란  

a라는 객체가 있고, 전역함수로써 혹은 b객체에 test()라는 메서드가 있다고 치자.

b.test()라고 실행되는게 보통이지만 이것을 마치 a객체에서 실행되게 ( a.test() 와 같은 효과 )하는 경우라 할 수 있다.


즉 메서드와 객체를 묶어놓는 것을 바인딩이라 하겠다.


코드 재사용 패턴부분의 메서드 빌려쓰기 부분이다. 

바인딩을 위해 이용한 call(), apply()를 설명한다.


어떤 객체에서 메서드 한두개만 마음에 드는 경우가 있다. 

이 메서드들을 재사용하고 싶지만  이 객체와 부모-자식관계까지 만들고 싶지는 않다. 


메서드 빌려쓰기 패턴을 사용하면 된다.  이 패턴은 함수의 메서드인 call()과 apply()를 활용한다.

call()은 호출하는 함수의 매개변수를 별개의 인자들로 받고 apply()는 배열로 받는다는 점이 다르다. 

즉 아래와 같다.

call( object, param1, param2..... );

apply( object, [param1, param2....] );


//call예제 

notmyobj.doStuff.call( myobj, param1, p2, p3 );

//apply예제

notmyobj.doStuff.apply( myobj, [param1, p2, p3] );



myobj라는 객체가 있고 notmyobj라는 객체는 doStuff라는 유용한 메서드를 가지고 있다고 하자.

상속을 거쳐 myobj가 필요하지 않은 모든 메서드를 물려받기보다는 간단히 doStuff()메서드만 일시적으로 빌려써 보자

call이나 apply에 객체와 인자를 전달하면, 빌려쓰는 메서드의 this에 인자로 전달한 객체가 바인딩된다.

인자값으로 전달된 객체가 잠시동안 메서드의 주인 객체처럼 행세하게 되는 것이다.

마치 상속세를 내지 않고 상속을 받는 것과 같다.( 여기서 상속세는 필요없는 프로퍼티와 메서드까지 물려받게 되는걸 말한다 )



배열 메서드 빌려쓰기


-arguments와 같이 배열과 비슷한 객체들이 배열의 slice()같은 메서드를 빌려쓸수 있다.

function f(){
var args=[].slice.call( arguments, 1, 3 );
return args;
}
f(1, 2, 3, 4, 5, 6); //[2,3]이 반환된다.


배열메서드를 사용하기 위해 빈 배열을 생성했다.

좀더 길게 쓰면 Array.prototype.slice.call()을 사용하여 Array의 프로토타입에서 직접 메서드를 빌려올 수 잇다.

이렇게 하면 코드는 약간 더 길어지지만, 빈 배열을 만드는 작업을 생략할 수 있다.



빌려쓰기와 바인딩


call()이나 apply()를 사용하거나 단순한 할당을 통해 메서드를 빌려오게 되면,

빌려온 메서드 안에서 this가 가리키는 객체는 호출식에 따라정해지게 된다.

그러나 어떤 경우에는 this값을 '고정'시키거나, 특정 객체에 바인딩되도록 처음부터 정해놓는것이 최선일때가 있다.



//one이라는 객체가 있고 이객체는 say()라는 메서드를 가진다.
var one={
name:"object",
say:function(greet){
return greet+","+this.name;
}
}
one.say( "hi" ); //"hi, object"


또 다른 객체 two는 say()메서드를 갖고 있지 않지만 one에서 빌려올 수 있다.
var two={
name:"another object"
}
one.say.apply( two, ['hello'] ); //"hello, another object"


say()내부의 this가 two를 가리키고 있기 때문에 this.name은 "another object"가 된다.




이 함수를 콜백 함수로 전달하는 경우에는? 

//함수를 변수에 할당하면 함수 안의 this는 전역객체를 가르키게 된다.
var say=one.say;
say( 'hoho' ); //"hoho, undefined"

//콜백 함수로 전달한 경우
var yetanother={
name:"Yet another object",
method: function (callback){
return callback( 'Hola' );
}
};
yetanother.method( one.say ); //"Holla, undefined"

예제에서 두가지 모두 say()안의 this가 전역객체를 가리키기 때문에 코드가 제대로 동작하지 않는다.

메서드와 객체를 묶어놓기 위해서는(바인딩하기위해서는) 다음과 간단한 함수를 사용할 수 있다.



function bind( o, m ){
return function(){
return m.apply(o, [].slice.call( arguments) );
}
}

var twosay=bind( two, one.say );
twosay('yo');

bind()함수는 o라는 객체와 m이라는 메서드를 인자로 받은 다음, 이 둘을 바인딩한 새로운 함수를 반환한다.

반환되는 새로운 함수는 클로저를 통해 o와 m에 접근할 수 있다. 

twosay()는 전역함수로 생성되었지만 this가 전역객체를 가리키지 않고 bind()에 전달된 two 객체를 가리킨다.

twosay() 함수를 어떻게 호출하든, this는 항상 two에 바인딩되어 있을 것이다.

클로저 하나 추가로 사용된 것이 바인딩 유지하는데 드는 비용이라 할 수 있다.



참고 : Javascript Pattern 참고

728x90
반응형

'Programming language > javascript' 카테고리의 다른 글

함수2  (0) 2013.02.06
함수1  (0) 2013.02.06
클로저(closure)란?  (0) 2013.02.06
가변길이 전달 인자 목록 : Arguments객체  (0) 2013.02.06
자바스크립트에서의 this란~  (0) 2013.02.06
댓글