JavaScript는 메소드 오버로딩이 없다.
매개변수의 갯수나, 속성, 리턴값의 일치여부를 체크하지 않는다.
함수를 선언하고 해당 함수가 호출되기 전 동일 네임의 함수가 다시 선언되는 경우 그대로 덮어쓴다.
하지만 메소드 오버로딩의 구현은 가능하다.
이를 구현한 소스가 있다.
자바스크립트의 전도사로, jQuery의 개발자로 유명한 John Resig의 소스이다.
원글 : http://ejohn.org/blog/javascript-method-overloading
아래와 같다.
02.
function
addMethod(object, name, fn){
03.
var
old = object[name];
04.
object[name] =
function
(){
05.
if
(fn.length == arguments.length)
06.
return
fn.apply(
this
, arguments);
07.
else
08.
if
(
typeof
old ==
'function'
)
09.
return
old.apply(
this
, arguments);
10.
};
11.
}
12.
13.
// Now setup the methods
14.
function
Users(){
15.
addMethod(
this
,
"find"
,
function
(){
16.
// Find all users...
17.
});
18.
addMethod(
this
,
"find"
,
function
(name){
19.
// Find a user by name
20.
});
21.
addMethod(
this
,
"find"
,
function
(first, last){
22.
// Find a user by first and last name
23.
});
24.
}
25.
26.
// Now use the methods
27.
var
users =
new
Users();
28.
users.find();
// Finds all
29.
users.find(
"John"
);
// Finds users by name
30.
users.find(
"John"
,
"Resig"
);
// Finds users by first and last name
31.
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 메소드의 함수 선언 (실행이되는 부분이 아닌 선언부분임)
- 15Line에서 addMethod가 호출되며 인수로 3개가 넘어간다.
- 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의 선언 부분 실행됨.)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 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의 선언 부분 실행됨.)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=1인 user.find 선언 부분 호출)
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 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의 선언 부분 실행됨.)
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
- 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
- 결국 아무것도 리턴되지 않고 종료
- 선언된 순서와 반대로 users.find 선언 부분이 호출된다. (fn.length=2인 user.find 선언 부분 호출)
- Users객체에 담겨있는 addMethod의 치환 부분이 호출된다.
차근차근 실행된 순서들을 읽어나가다 보면 어찌하여 실행이 되었는지 알 수 있을 것이다.
사용된 JavaScript의 메소드는 다음과 같다.
2.
alert(testFunction.length);
//호출 : 매개변수의 갯수 2
3.
alert(arguments.length);
//호출 : 인수의 갯수 3
4.
}
5.
testFunction(
"값1"
,
"값2"
,
"값3"
);
functionObj.length는 기능함수에서 정의된 인수의 갯수이고
functionObj.arguments.length는 기능함수가 호출될 때 전달받은 인수의 갯수이다.
나머지 사항은 이전에 언급한 적이 있던 함수의 호출 을 참조하여 흐름에 대해 파악하면 될 것이다.
주의해야 하는 점은 new 전치연산자로 생성자가 Users의 addMethod를 선언한 내용을 실제 메소드 호출을 할 때 선언을 한 순서의 역순으로 실행을 한다는 점이다.