본문 바로가기
Programming

[Javascript] 일급 객체(First-class Object)란 무엇인가?

by 개발자 염상진 2022. 5. 8.

What is first-class function in Javasript?

 

일급 객체(fisrt-class Object)란?

 

Javascript에서 함수는 객체로 사용 가능하다. 객체는 값을 가진 데이터 이므로 함수를 데이터로 사용가능하다는 말이다. Javascript가 함수형 프로그래밍을 가능하게 하는 가장 큰 장점 중 하나다.

 

함수를 객체로 사용한다는 말이 무엇일까? 일급 객체의 조건은 다음 4가지 조건을 충족하면 된다. Javascript는 아래의 조건에 더해 직접 호출을 할 수도 있고, 고유 property를 소유하고 있는 특별한 존재다.

 

일급 객체(first class Object) 조건

 

① 무명의 리터럴로 생성가능하다. (런타임에 생성 가능)

② 변수나 자료구조(배열, 객체)에 저장 가능하다.

③ 함수의 매개변수에 전달 가능하다.

④ 함수의 반환값으로 사용 가능하다.

 

 

 

함수의 property?

 

Javascript의 함수는 고유의 property를 가지고 있다. console.dir()를 찍어보면 함수가 가진 property들이 출력된다. 함수의 property를 확인하기 위해서는 console.dir()를 사용하는 방법과 Object.getOwnPropertyDescriptors() 메소드를 사용하는 것, 마지막으로 접근자 프로퍼티를 이용한 Object.getOwnPropertyDescriptior(Object.prototype, '__proto__')를 사용하는 3가지 방법이 있다.

 

function test(){
}

// console.dir(test)

[[Prototype]]: ƒ ()
apply: ƒ apply()
arguments: (...)
bind: ƒ bind()
call: ƒ call()
caller: (...)
constructor: ƒ Function()
length: 0
name: ""
toString: ƒ ()
Symbol(Symbol.hasInstance): ƒ [Symbol.hasInstance]()
get arguments: ƒ ()
set arguments: ƒ ()
get caller: ƒ ()
set caller: ƒ ()
[[FunctionLocation]]: ​
[[Prototype]]: Object
[[Scopes]]: Scopes[0]

// console.log(Object.getOwnPropertyDescriptors(test))
arguments: {value: null, writable: false, enumerable: false, configurable: false}
caller: {value: null, writable: false, enumerable: false, configurable: false}
length: {value: 0, writable: false, enumerable: false, configurable: true}
name: {value: 'test', writable: false, enumerable: false, configurable: true}
prototype: {value: {…}, writable: true, enumerable: false, configurable: false}
[[Prototype]]: Object

//console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
configurable: true
enumerable: false
get: ƒ __proto__()
length: 0
name: "get __proto__"
arguments: (...)
caller: (...)
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[0]
set: ƒ __proto__()
[[Prototype]]: Object

 

 

위에서 보는 것 처럼 Javascript 함수는 함수 고유의 Property(arguments, caller, length, name, prototype)을 받고 있고, Object.prototype의 Property를 상속받고 있다. 모든 객체가 __proto__ 접근자 프로퍼티를 사용할 수 있지만 함수만이 자신만의 고유의 프로퍼티를 사용할 수 있다.

 

 

Javascript Function arguments 프로퍼티

 

함수가 가지는 arguments 프로퍼티는 arguments 객체를 의미한다. arguments 객체는 함수가 인자로 전달받는 매개변수의 정보를 담은 유사배열 객체다. 외부에서 참조는 불가능하며 순회하면서 함수 내부에서 사용가능하다.

 

함수 내에서 모든 인수는 arguments 객체의 프로퍼티에 저장된다. 함수 내부에서 arguments를 찍어보면 매개변수를 프로퍼티 값으로 가진 객체를 확인할 수 있다.

 

function test(){
	// 함수의 arguments 객체를 출력
    console.log(arguments);
}

test();
test(1);
test(1,2);
[Arguments] {}
[Arguments] { '0': 1 }
[Arguments] { '0': 1, '1': 2 }

 

 

함수의 arguments 객체를 살펴보면 [인수값, callee, length, Symbol]로 구성되어 있다. 인수값은 매개변수로 전달받은 데이터를 의미한다. length는 매개변수의 길이를 의미한다. callee는 호출되어 arguments 객체를 생성하는 함수다. 마지막으로 Symbol은 arguments 객체를 순회 가능한 자료구조[iterator]로 만들기 위한 프로퍼티다. 

 

arguments를 이터러블로 만들기 위해서는 프로퍼티 키 값으로 Symbol.iterator를 이용한 메소드를 구현해주면 된다. 

 

function test(){

    const iterator = arguments[Symbol.iterator]();

    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
}

test(1,2,3);

 

ES6에서는 arguments 객체를 대신하는 Rest 파라미터가 도입되었다. 기존의 arguments는 유사 배열 객체였기 때문에 직접적인 배열 메소드를 사용할 수가 없다. 배열로 변환하는 수고로움을 덜기위해서 만들어진 Rest parameter는 배열 메소드를 바로 사용할 수 있다.

 

// Rest Parameter 사용

function test(...restParameters){

    return restParameters.reduce((pre, cur) => {
        return pre+cur
    }, 0);
}

console.log(test(1,2,3));
// Rest Parameters는 배열로 사용가능하다. 
function test(...restParameters){

    return restParameters.map((item)=>item*item);
}

console.log(test(1,2,3));

 

 

 

Javascript Prototype property

 

prototype property는 생성자 함수로 호출할 수 있는 함수 객체만이 가지는 고유한 property다. 즉 일반 객체는 prototype property를 가지지 않는다. hasOwnProperty() 함수는 객체 고유의 프로퍼티인 경우 true를 반환한다. 

 

// 함수 생성
function test1(){
}

// prototype을 가지는 함수 객체
console.log(test1.hasOwnProperty('prototype'));

 

댓글