일급 객체는 다음의 조건을 만족하며, 객체와 동일하게 취급 되어 값이 사용될 수 있는 곳에 사용 되는 함수를 의미합니다.
이러한 일급 객체가 일반 객체간의 비교에서 차이를 보일 수 있는 결정적 차이점이라고 한다면 일반 객체는 호출을 할 수 없지만, 일급 객체(함수)는 호출을 할 수 있다는대에 그 차이점을 두죠.
자바스크립트에서는 함수를 일급 객체로 보시는게 좀 더 이해하기 편하실 것 같습니다.
// ① 변수나 자료구조(객체 배열 등)의 프로퍼티에 저장될 수 있습니다. const add = function(a, b) { // 함수도 객체이므로 add 변수에 저장이 가능합니다. return a + b; }; const person = { //또한 객체의 프로퍼티 sayhello의 값으로 할당 가능합니다. name : "Re_Go", age : 30, sayhello : function(){ console.log(`안녕하세요! 저는 ${this.name} 입니다~`) } } person.sayhello() // 안녕하세요! 저는 Re_Go 입니다~ 출력 // ② 함수의 매개변수에 전달할 수 있습니다. 이때 매개변수로 전달 된 함수를 콜백함수(callback Function)이라고 하며, 전달을 받은 쪽의 함수를 고차함수(higher-order Function)라고 합니다. 예제에서 고차함수는 applyOperation에 속하며, 콜백함수는(add)에 속합니다. 단 코드의 작성 상황에 따라 포지션은 언제든지 바뀔 수 있습니다. function add(a,b){ // applyOperation으로부터 전달 받은 인자를 처리하고 반환합니다. return a+b; } function applyOperation(a, b, operation) { //전달 받은 함수(세번째 매개변수)를 호출하고 나머지 두 매개변수(a와 b)를 인자로 전달합니다. return operation(a, b); // 해당 함수에 의해 반환된 값을 또 반환하고 종료합니다. } applyOperation(1,2,add) // 피연산자 둘과 함수를 인자로 보냅니다. // ③ 함수의 반환값으로 사용할 수 있다. function createMultiplier(factor) { // 전달 받은 객체 factor를 createMultiplier 함수 내부의 함수에 의해 return 되는 용도로 사용됩니다. return function(x) { // 함수 내부에서 함수를 호출하여 반환 된 값을 반환합니다. 즉 함수 내부에서 또 다른 함수가 실행되어 값을 반환하는 용도로 사용이 될 수 있는 것이죠. return x * factor; }; }
결국 자바스크립트에서 일급 객체란 함수를 의미한다고 보시면 되는데요. 이러한 일급 객체 또한 큰 틀에서 보자면 객체와 다를 바 없기 때문에 console.dir(일급 객체) 메서드나 Object.getOwnPropertyDescriptors(일급 객체) 메서드로 해당 객체의 프로퍼티를 확인 할 수 있습니다.
단일급 객체(함수)는 일반 객체에서는 가질 수 없는 프로퍼티들을 가지고 있습니다. 다음은 해당 프로퍼티와 그에 대한 설명의 소개입니다.
arguments 프로퍼티 :
함수 호출시 전달된 인수들의 정보를 담고 있는, 순회 가능한 유사 배열 객체의 형태를 띄고 있으며 전달 받은 함수 내부에서 지역 변수처럼 사용이 가능합니다.단 외부에서 arguments를 당연하게도 참조할 수 없으며, 객체에 전달된 인자의 수에 비해 객체에서 지정된 매개변수의 수가 부족할 경우 자리를 채우지 못한 인자들이 arguments에 보관된다고 보시면 되겠습니다.
또한 이러한 arguments는 유사 배열 객체이므로 다른 메서드에 의해 순회 및 열거는 가능하나, 배열 메서드를 직접적으로 사용하지는 못하고, from메서드, call과 apply 메서드의 조합 등으로 다른 배열 변수에 옮겨 담을때 사용이 가능합니다.
참고로 ES6부터 등장한 화살표 함수에서는 arguments 프로퍼티를 사용할 수 없으므로 rest 연산자(...args) 로 대체되었다는 점을 참고하시기 바랍니다. (물론 일반 함수에서도 rest 연산자를 사용 가능합니다.)
// ① 초과된 인수를 arguments로 활용하는 코드 예시) 이러한 이유로 arguments를 사용하는 함수를 가변 인자 함수라고 부르기도 합니다. function multifly(a,b){ // 인수를 두 개 받는다면 6은 무시가 되는데 let sum = 1; for(let i = 0 ; i < arguments.length ; i++){ sum *= arguments[i] //이때 arguments는 순회 가능한 유사 배열 형태로 인수들(무시된 6까지도)을 보관하고 있기 때문에 배열 형태로 사용. } return sum; } console.log(multifly(1,2,6)); // ② arguments 대신 Rest 파라미터를 사용하여 매개 변수들을 활용하는 방법 function sum(...args){ //args 앞에 스프레드 연산자(rest)를 입력할 경우 args는 넘어온 매개변수를 전부 보관하고 있는 배열 형태의 매개변수가 됩니다. return args.reduce((pre, cur) => pre + cur, 0); // 배열 객체에 사용 가능한 reduce 메서드를 활용해 넘어온 매개변수들을 보관하는 args 매개배열을 순회하며 누적합 연산의 결과값을 반환합니다. 만약 ...rest가 아니라 arguments를 사용했다면 배열 메서드인 reduce를 사용하지 못했을 겁니다. } console.log(sum(1,2,3)) // 반환값 6 출력 console.log(sum(1,2,3,4,5)) // 반환값 15 출력
- caller 프로퍼티 : caller 속성은 함수를 호출한 함수를 나타냅니다. 이 속성은 더 이상 지원되지 않으므로, 이 프로퍼티 대신 Function.prototype.caller 프로퍼티를 확인하여 호출자를 확인할 수 있습니다.
function getCaller() { console.log(getCaller.caller); } function topLevelFunction() { getCaller(); } topLevelFunction(); // 출력: function topLevelFunction() { getCaller(); }
- length 프로퍼티 :
인수를 전달 받는 함수가 가지는 매개변수의 개수를 나타내며 넘어오는 인수값과는 별개이므로 사용시 주의가 필요합니다.function add(a,b){ console.log(add.length) // 매개변수 a와 b 두개를 가지고 있으므로 2 출력 return a+b; } function add(...args){ console.log(add.length) // 함수의 length 프로퍼티는 확산 연산자를 사용한 매개변수에 대해서는 함수 시그니처에 해당하지 않으므로 배열에 인자로 넘어온 다섯개의 값을 가지고 있더라 하더라도 없이 취급되기 때문에 0이 출력됩니다. return args.reduce((pre, cur) => pre + cur, 0); } console.log(add(1,2,3,4,5));
name 프로퍼티 :
ES6 부터 정식 표준이 된 프로퍼티로 함수의 이름을 나타냅니다. 또한 익명 함수 표현식에 대한 name 프로퍼티를 사용시 ES5 까지는 빈 문자열(이름이 없는 함수 선언 종류이기 때문에)을 나타냈지만,ES6 부터 함수 객체를 가리키는 식별자인 anonymousFunc를 나타내게 됩니다. (버전의 문제이므로 일부로 버전을 ES5로 다운그레이드 하지 않는 한 신경쓰지 않아도 됩니다.)
function exampleFunction() { console.log(exampleFunction.name); } exampleFunction(); // 출력: exampleFunction
- prototype 프로퍼티 :
함수의 프로토타입 객체를 나타냅니다. 주로 생성자 함수에서 사용되며, 오직 constructor만 갖고 있는 프로퍼티이기도 합니다. 이 프로퍼티의 주된 목적은 해당 일급 객체(함수) 가 생성자 함수로서 호출될 때 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리키는데 사용됩니다.