자바스크립트에서 함수는 객체다. 따라서 함수도 프로퍼티를 갖는다.
함수 객체는 기본적으로 총 5가지의 프로퍼티를 갖는다.
Object의 정적 메서드
getOwnPropertyNames
는 전달된 객체의 모든 속성들을 배열로 반환해 준다.
위에서 작성한 getSumOfNumbers 함수
를 예시로, 5가지의 프로퍼티가 각각 무슨 뜻인지 확인해 보자!
함수 객체의 length
프로퍼티는 함수를 정의할 때 선언한 매개변수의 개수를 가리키는 프로퍼티다.
getSumOfNumbers 함수는 3개의 매개변수(num1, num2, num3)를 갖는 함수다. 따라서 length 프로퍼티 값을 조회해 보면, 3이 나온다.
매개변수의 개수를 다양하게 정의해 length 프로퍼티를 참조해 보자.
단, Rest 파라미터
로 함수를 정의하면 함수의 length 프로퍼티 값은 0이다.
함수 객체의 name
프로퍼티는 함수의 이름을 나타내는 프로퍼티다.
가명 함수
를 변수에 할당하면 즉, 가명 함수 표현식
을 사용하면 변수가 가리키는 함수의 name 프로퍼티는 변수명이 아닌 함수명이 된다.
익명 함수
를 만들어 변수에 할당하면 즉, 익명 함수 표현식
을 사용하면 변수가 가리키는 함수(익명 함수)의 name 프로퍼티는 변수 이름과 동일하다.
단,
ES5
에서익명 함수 표현식
으로 작성한 함수의 name 프로퍼티는 빈 문자열이다. ES6에서 함수 객체를 가리키는 식별자를 값으로 갖도록 변경되었다.
함수 객체의 caller
프로퍼티는 함수 자신을 호출한 함수를 가리킨다.
단, caller는 ECMAScript 사양에 포함되지 않은 비표준 프로퍼티로, 사용하지 않는 것이 좋다.
→ getSumOfNumbers 함수가 호출된 곳은 calling 함수 내부기 때문에, getSumOfNumbers의 caller는 calling이 된다.
함수 객체의 prototype
프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때, 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킨다. 생성자 함수로 호출할 때 의미가 있는 프로퍼티기 때문에, 생성자 함수로써 호출할 수 없는 non-constructor에는 prototype 프로퍼티가 없다.
함수 객체의 arguments
프로퍼티는 함수 호출 시 전달된 인수들의 정보를 담고 있는 이터러블한(순회 가능한) 유사 배열 객체다. 함수 내부에서 지역 변수처럼 사용할 수 있고 외부에선 참조할 수 없다.
즉, 함수를 호출할 때 전달된 인수는 arguments
프로퍼티에 저장된다. 이때 arguments 객체는 인수를 프로퍼티 값으로 소유하고, 프로퍼티 키는 인수의 순서를 나타낸다.
function getSumOfNumbers(num1, num2, num3) {
console.log(arguments);
return num1 + num2 + num3;
}
→ 전달한 인수 1, 2, 3이 arguments 프로퍼티에 저장되었다.
자바스크립트는 함수의 매개변수와 호출 시 전달한 인수의 개수가 일치하는지 확인하지 않는다. 따라서 매개변수의 개수만큼 인수를 전달하지 않더라도 에러가 발생하지 않는다.
정의한 함수를 호출하면 함수 평가 과정을 거치면서 함수 몸체 내에 암묵적으로 매개변수가 선언되고 undefined로 초기화한 다음, 전달한 인수를 재할당한다. 즉, 인수를 전달하지 않으면 매개변수는 undefined다.
function getSumOfNumbers(num1, num2, num3) {
console.log(arguments);
console.log('num1: ', num1);
console.log('num2: ', num2);
console.log('num3: ', num3);
return num1 + num2 + num3;
}
→ num2와 num3이 undefined기 때문에 getSumOfNumbers 함수의 리턴은 계산 불가로 NaN을 반환한다.
매개변수 개수보다 많은 인수를 전달한 경우, 초과된 인수는 무시한다. 단, 초과된 인수는 버려지는 것이 아니라 함수의 arguments 객체에 프로퍼티로 보관된다.
function getSumOfNumbers(num1, num2, num3) {
console.log(arguments);
return num1 + num2 + num3;
}
→ 초과된 인수(4와 5)까지 Arguments 객체에 보관된다.
이렇게 arguments 객체는 초과된 인수까지 저장하기 때문에, 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하게 쓸 수 있다.
arguments 객체는 배열 형태로 정보를 가지고 있어 순회가 가능하지만, 실제로 배열이 아닌 (유사 배열) 객체다.
유사 배열 객체
는 배열처럼length
프로퍼티를 가지고 있어 for문으로 순회 가능하다.
매개변수를 따로 정의하지 않고도, arguments
객체를 참조하면 함수 호출 시 전달 받은 인수 정보를 알 수 있다.
단, arguments 객체는 배열이 아닌 유사 배열 객체기 때문에 배열 메서드를 사용할 수 없다.
유사 배열 객체에 배열 메서드를 사용하려면 call, apply 메서드를 사용해 간접 호출해야 한다.
이러한 단점을 보완하기 위해 ES6에서 도입된 Rest
파라미터를 사용할 수 있다.
Rest 파라미터는 매개변수 이름 앞에 …
을 붙여 정의한 매개변수를 말하며, 함수에 전달된 인수들의 목록을 배열
로 전달받을 수 있다.
위에서 작성한 모든 인수를 더하는 함수
를 rest
파라미터를 사용해 리팩터링하면 다음과 같다.