Study/JavaScript
[JavaScript][source analysis] 메소드 오버로딩
Bluesky_
2009. 4. 16. 02:36
반응형
JavaScript는 메소드 오버로딩이 없다.
매개변수의 갯수나, 속성, 리턴값의 일치여부를 체크하지 않는다.
함수를 선언하고 해당 함수가 호출되기 전 동일 네임의 함수가 다시 선언되는 경우 그대로 덮어쓴다.
하지만 메소드 오버로딩의 구현은 가능하다.
이를 구현한 소스가 있다.
자바스크립트의 전도사로, jQuery의 개발자로 유명한 John Resig의 소스이다.
원글 : http://ejohn.org/blog/javascript-method-overloading
아래와 같다.
// addMethod - By John Resig (MIT Licensed)
function addMethod(object, name, fn){
var old = object[name];
object[name] = function(){
if (fn.length == arguments.length)
return fn.apply(this, arguments);
else
if (typeof old == 'function')
return old.apply(this, arguments);
};
}
// Now setup the methods
function Users(){
addMethod(this, "find", function(){
// Find all users...
});
addMethod(this, "find", function(name){
// Find a user by name
});
addMethod(this, "find", function(first, last){
// Find a user by first and last name
});
}
// Now use the methods
var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name
users.find("John", "E", "Resig"); // Does nothing
짧고 간결하다.하지만 짧은 코드안에 참 많은 함축적인 JavaScript의 문법들이 들어있다.
프로세스의 순서대로 나열해보자.
- 페이지가 호출되면 함수 선언부들이 라인별로 읽어들여진다.
- 27Line에서 new 전치 연산자로 Users함수가 생성자로 호출이 된다.
- Users 생성자는 this에 바인딩되며 생성자의 본문 내용을 메모리에 로드한다.
- addMethod를 만나고 addMethod의 본문이 치환되어 불려들여진다.
- 15Line에서 addMethod가 호출되며 인수로 3개가 넘어간다.
- old라는 변수에 users.find가 참조된다. (현재 users.find가 없으므로 undefined가 참조됨)
- users.find 메소드의 함수 선언 (실행이되는 부분이 아닌 선언부분임)
- 15Line에서 addMethod가 호출되며 인수로 3개가 넘어간다.
- old라는 변수에 users.find가 참조된다. (2-A-1-A에서 선언된 fn.length=0인 users.find가 참조됨)
- users.find 메소드의 함수 선언 (실행이되는 부분이 아닌 선언부분임)
- 21Line에서 addMethod가 호출되며 인수로 3개가 넘어간다.
- old라는 변수에 users.find가 참조된다. (2-A-1-B에서 선언된 fn.length=0인 users.find가 참조됨)
- users.find 메소드의 함수 선언 (실행이되는 부분이 아닌 선언부분임)
- 28Line에서 users.find() 메소드가 호출된다.
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=0 이므로 false)
- 8Line에서 이전 2-A-1-C-1에서 참조된 typeof old == 'function' true
- 참조되어 있던 2-A-1-B-2 메소드가 다시 users.addMethod에 선언부분으로 참조 변경됨. (2-A-1-C-2 -> 2-A-1-B-2로 참조 변경)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=1인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=0 이므로 false)
- 8Line에서 이전 2-A-1-B-1에서 참조된 typeof old == 'function' true
- 참조되어 있던 2-A-1-A-2 메소드가 다시 users.addMethod에 선언부분으로 참조 변경됨. (2-A-1-B-2 -> 2-A-1-A-2로 참조 변경)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=0인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 true (28Line의 호출된 users.find 메소드의 arguments=0 이므로 true)
- 6Line에서 이전 2-A-1-A-1에서 참조된 users.find 선언 부분이 실행된다. (16Line의 선언 부분 실행됨.)
- 29Line에서 users.find("John") 메소드가 호출된다.
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=1인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=1 이므로 false)
- 8Line에서 이전 2-A-1-C-1에서 참조된 typeof old == 'function' true
- 참조되어 있던 2-A-1-B-2 메소드가 다시 users.addMethod에 선언부분으로 참조 변경됨. (2-A-1-C-2 -> 2-A-1-B-2로 참조 변경)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=1인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 true (28Line의 호출된 users.find 메소드의 arguments=1 이므로 true)
- 6Line에서 이전 2-A-1-B-1에서 참조된 users.find 선언 부분이 실행된다. (19Line의 선언 부분 실행됨.)
- 30Line에서 users.find("John") 메소드가 호출된다.
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 true (28Line의 호출된 users.find 메소드의 arguments=2 이므로 true)
- 6Line에서 이전 2-A-1-A-1에서 참조된 users.find 선언 부분이 실행된다. (22Line의 선언 부분 실행됨.)
- 31Line에서 users.find("John", "E", "Resig") 메소드가 호출된다.
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=3 이므로 false)
- 8Line에서 이전 2-A-1-C-1에서 참조된 typeof old == 'function' true
- 참조되어 있던 2-A-1-B-2 메소드가 다시 users.addMethod에 선언부분으로 참조 변경됨. (2-A-1-C-2 -> 2-A-1-B-2로 참조 변경)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=1인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=3 이므로 false)
- 8Line에서 이전 2-A-1-B-1에서 참조된 typeof old == 'function' true
- 참조되어 있던 2-A-1-A-2 메소드가 다시 users.addMethod에 선언부분으로 참조 변경됨. (2-A-1-B-2 -> 2-A-1-A-2로 참조 변경)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=0인 user.find 선언 부분 호출)
- fn.length와 호출된 users.find 비교 결과 false (28Line의 호출된 users.find 메소드의 arguments=3 이므로 false)
- 8Line에서 이전 2-A-1-A-1에서 참조된 typeof old == 'function' false
- 결국 아무것도 리턴되지 않고 종료
차근차근 실행된 순서들을 읽어나가다 보면 어찌하여 실행이 되었는지 알 수 있을 것이다.
사용된 JavaScript의 메소드는 다음과 같다.
function testFunction(value1, value2) {
alert(testFunction.length); //호출 : 매개변수의 갯수 2
alert(arguments.length); //호출 : 인수의 갯수 3
}
testFunction("값1", "값2", "값3");
functionObj.length는 기능함수에서 정의된 인수의 갯수이고
functionObj.arguments.length는 기능함수가 호출될 때 전달받은 인수의 갯수이다.
나머지 사항은 이전에 언급한 적이 있던 함수의 호출 을 참조하여 흐름에 대해 파악하면 될 것이다.
주의해야 하는 점은 new 전치연산자로 생성자가 Users의 addMethod를 선언한 내용을 실제 메소드 호출을 할 때 선언을 한 순서의 역순으로 실행을 한다는 점이다.
반응형