함수에는 arguments 라는 변수에 담긴 숨겨진 유사배열이 있습니다. 아래의 예제에는 함수를 호출할 때 입력한 인자가 담겨있습니다. 결과는 10입니다.
<!DOCTYPE html> <html> <head> </head> <body> <script type="text/javascript"> function sum(){ var i, _sum = 0; for(i = 0; i < arguments.length; i++){ document.write(i+' : '+arguments[i]+'<br />'); _sum0 += arguments[i]; } return _sum; } document.write('result : ' + sum(1,2,3,4)); </script> </body> </html>
함수 sum은 인자로 전달된 값을 모두 더해서 리턴하는 함수입니다. 그런데 1행처럼 함수
sum
은 인자에 대한 정의하가 없습니다. 하지만 마지막 라인에서는 4개의 인자를 함수sum
으로 전달하고 있습니다. 함수의 정의부분에서 인자에 대한 구현이 없음에도 인자를 전달할 수 있는 것은 왜 그런걸까요? 그것은arguments
라는 특수한 배열이 있기 때문입니다.
arguments
는 함수안에서 사용할 수 있도록 그 이름이나 특성이 약속되어 있는 일종의 배열입니다.arguments[0]
은 함수로 전달된 첫번째 인자를 알아낼 수 있습니다. 또arguments.length
를 이용해서 함수로 전달된 인자의 개수를 알아낼 수도 있습니다. 이러한 특성에 반복문을 결합하면 함수로 전달된 인자의 값을 순차적으로 가져올 수 있습니다. 그 값을 더해서 리턴하면 인자로 전달된 값에 대한 총합을 구하는 함수를 만들 수 있습니다.
arguments는 사실 배열이 아닙니다. 실제로는 arguments 객체의 인스턴스입니다.
매개변수와 관련된 두가지 수가 있습니다. 하나는 함수.length이고, 다른 하나는 arguments.length 입니다. arguments.length는 함수로 전달 된 실제 인자의 수를 의미하고, 함수.length는 함수에 정의된 인자의 수를 의미합니다.
function zero(){ console.log( 'zero.length', zero.length, 'arguments', arguments.length ); } function one(arg1){ console.log( 'one.length', one.length, 'arguments', arguments.length ); } function two(arg1, arg2){ console.log( 'two.length', two.length, 'arguments', arguments.length ); } zero(); // zero.length 0 arguments 0 one('val1', 'val2'); // one.length 1 arguments 2 two('val1'); // two.length 2 arguments 1
zero.length, one.length...는 파라미터의 개수이고, arguments.length는 인자의 개수입니다.
따라서, 아래의 그림과 같이 결과가 출력되는 것을 볼 수가 있습니다.
함수를 호출하는 가장 기본적인 방법은
function func(){ } func();
javascript는 함수를 호출하는 특별한 방법을 제공합니다. 위의 예제에서는 함수 func는 function이라는 객체의 인스턴스입니다. 따라서 func는 객체 function이 가지고 있는 메소드들을 상속하고 있습니다. function.apply과 function.call 이 메소들을 이용해서 아래의 예제처럼 함수를 호출해봤습니다. 결과는 3이라는 것을 볼 수 있습니다.
function sum(arg1, arg2){ return arg1+arg2; } alert(sum.apply(null, [1,2]))
함수 sum은 function 객체의 인스턴스입니다. 그렇기 때문에 객체 function의 메소드 apply를 호출 할 수 있습니다. apply 메소드는 두 개의 인자를 가질 수 있는데, 첫 번째 인자는 함수(sum)가 실행될 맥락입니다. 두 번째 인자는 배열인데, 이 배열의 담겨있는 원소가 함수(sum)의 인자로 순차적으로 대입됩니다.
function sum(){ var _sum = 0; for(name in this){ _sum += this[name]; } return _sum; } o1 = {val1:1, val2:2, val3:3, sum:sum} o2 = {v1:10, v2:50, v3:100, v4:25, sum:sum} alert(o1.sum()); alert(o2.sum());
o1는 3개의 속성을 가지고 있습니다. 각각의 이름은 val1, val2, val3입니다. o2는 4개의 속성을 가지고 있고 o1과는 다른 속성 이름을 가지고 있고 속성의 수도 다릅니다. 그 다음엔 함수 sum을 만들었습니다. 이 함수는 객체의 속성을 열거할 때 사용하는 for in문을 이용해서 객체 자신(this)의 값을 열거한 후에 각 속성의 값을 지역변수 _sum에 저장한 후에 이를 리턴하고 있습니다. 객체 function의 메소는 apply의 첫번 째 인자는 함수가 실행될 맥락입니다. sum.apply(o1)은 함수 sum을 객체 o1의 메소드로 만들고 sum을 호출한 후에 sum을 삭제합니다.
우선 위의 예제처럼 코드를 작성하면 경고창에 이렇게 출력이 되는 걸 볼 수 있습니다.
수의 내용까지 같이 포함해서 나오는 걸 볼 수 있습니다. 왜 이렇게 결과물이 나왔냐면 o1과 o2의 sum이라는 속성을 추가 했기때문에 for문의 this를 열거하는 과정에서 자연스럽게 sum이라는 함수도 더하고 있기 때문에 이렇게 출력이 된 것을 볼 수 있습니다.
이것을 방지할라면 ' if(typeof this[name] !== 'function')' 조건문을 사용하면 되는데 이렇게 조건문을 넣게 되면function sum(){ var _sum = 0; for(name in this){ if(typeof this[name] !== 'function') _sum += this[name]; } return _sum; } o1 = {val1:1, val2:2, val3:3, sum:sum} o2 = {v1:10, v2:50, v3:100, v4:25, sum:sum} alert(o1.sum()); alert(o2.sum());
이렇게 코드를 작성하면 결과는 이렇게 출력이 됩니다.
차례대로 결과가 출력 되는 걸 볼 수가 있습니다.