티스토리 뷰
목차
[자바스크립트 강좌 006] JavaScript 클로저로 메서드 연결 (closure)
클로저는 성능적인 면과 자원적인 면에서 약간 손해를 볼 수 있으므로 무차별적으로 사용해서는 안 된다. 사실 클로저를 잘 활용하려면 경험이 가장 중요하게 작용한다.
여기서는 아주 전형적인 JavaScript 클로저의 예제 코드를 소개할 텐데, 어느 정도 클로저의 감각만이라도 얻어갈 수 있기를 바란다. 진정 좋은 자바스크립트 프로그래머가 되려면 많은 개발 경험을 쌓는 것이 가장 좋은 방법이다.
특정 함수에 사용자가 정의한 자바스크립트 객체의 메서드 연결하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function HelloFunc(func) { this.greeting = "hello"; } HelloFunc.prototype.call = function(func) { func ? func(this.greeting) : this. func(this.greeting); } var userFunc = function(greeting) { console.log(greeting); } var objHello = new HelloFunc(); objHello.func = userFunc; objHello.call(); | cs |
함수 HelloFunc는 greeting 변수가 있고, func 프로퍼티로 참조되는 함수를 call() 함수로 호출한다. 사용자는 func 프로퍼티에 자신이 정의한 함수를 참조시켜 호출할 수 있다. 다만, HelloFunc.prototype.call()을 보면 알 수 있듯이 자신의 지역 변수인 greeting만을 인자로 사용자가 정의한 함수에 넘긴다.
앞 Javascript 예제에서 사용자는 userFunc() 함수를 정의하여 objHello.func()에 참조시킨 뒤, HelloFunc()의 지역 변수인 greeting을 화면에 출력한다.
앞 코드를 실행하면 결과는 다음과 같다.
# hello
이 자바스크립트 예제에서 HelloFunc()는 greeting만을 인자로 넣어 사용자가 인자로 넘긴 함수를 실행시킨다. 그래서 사용자가 정의한 함수도 한 개의 인자를 받는 함수를 정의할 수밖에 없다. 여기서 사용자가 원하는 인자를 더 넣어서 HelloFunc()를 이용하여 호출하려면 어떻게 해야 할까?
[자바스크립트 클로저 예제] Javascript - Closure
다음 코드를 이어서 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function saySomething(obj, methodName, name) { return (function(greegint) { return obj[methodName](greeting, name); }); } function newObj(obj, name) { obj.func = saySomething(this, "who", name); return obj; } newObj.prototype.who = function(greeting, name) { console.log(greeting + " " + (name || "everyone") ); } | cs |
위 예제에서 새로운 함수 newObj()를 선언하였다.
이 함수는 HelloFunc()의 객체를 좀 더 자유롭게 활용하려고 정의한 함수이다. 첫 번째 인자로 받는 obj는 HelloFunc()의 객체가 되고, 두 번째 인자는 사용자가 출력을 원하는 사람 이름이 된다. newObj() 함수의 Javascript 객체를 다음과 같이 만들어보자.
1 | var obj1 = new newObj(objHello, "zzoon"); | cs |
앞 코드로 다음 클로저 코드가 실행된다.
1 2 3 | obj.func = saySomething(this, "who", name); return obj; | cs |
첫 번째 이자 obj의 func 프로퍼티에 saySomething() 함수에서 반환되는 함수를 참조하고, 반환한다. 결국 obj1은 인자로 넘겼던 objHello 객체에서 func 프로퍼티에 참조된 함수만 바뀐 객체가 된다.따라서 자바스크립트에서는 다음과 같이 호출할 수 있다.
1 | obj1.call(); | cs |
이 Javascript 코드의 실행결과, newObj.prototype.who 함수가 호출되어 사용자가 원하는 결과인 "hello zzoon"을 출력한다.
그렇다면 saySomething() 함수 안에서 어떤 작업이 수행되는지 살펴보자.
1 2 3 4 5 | function saySomething(obj, methodName, name) { return (function(greegint) { return obj[methodName](greeting, name); }); } | cs |
- 첫 번째 인자 : newObj 객체 - obj1
- 두 번째 인자 : 사용자가 정의한 메서드 이름 - "who"
- 세 번째 인자 : 사용자가 원하는 사람 이름값 - "zzoon"
- 반환 : 사용자가 정의한 newObj.prototype.who() 함수를 반환하는 helloFunc()의 func 함수
[자바스크립트 클로저 예제] Javascript - Closure
이렇게 반환되는 함수가 HelloFunc이 원하는 function(greeting) {} 형식의 함수가 되는데, 이것이 HelloFunc 객체의 func로 참조된다.
obj1.call()로 실행되는 것은 실질적으로 newObj.prototype.who()가 된다. 이와 같은 방식으로 사용자는 자신의 자바스크립트 객체 메서드인 who 함수를 HelloFunc에 연결할 수 있다. 여기서 Javascript 클로저는 saySomething()에서 반환되는 function(greeting) {}이 되고, 이 클로저는 자유 변수 obj.methodName, name을 참조한다.
[자바스크립트 클로저 예제] Javascript - Closure
앞 예제는 정해진 형식의 함수를 콜백해주는 라이브러리가 있으면, 그 정해진 형식과는 다른 형식의 사용자 정의 함수를 호출할 때 유용하게 사용된다.
예를 들어 브라우저에서는 onclick, onmouseover와 같은 프로퍼티에 해당 이벤트 핸들러를 사용자가 정의해 놓을 수가 있는데, 이 이벤트 핸들러의 형식은 function(event) {}이다. 이를 통해 브라우저는 발생한 이벤트를 event 인자로 사용자에게 넘겨주는 방식이다.
여기에 event 외의 원하는 인자를 더 추가한 이벤트 핸들러를 사용하고 싶을 때, 앞과 같은 방식으로 크롤저를 적절히 활용해줄 수 있다.
출처 : 인사이드 자바스크립트
[자바스크립트 강좌 006] JavaScript 클로저로 메서드 연결 (closure)