다음 조건을 만족하는 객체를 일급 객체라 한다.
자바스크립트의 함수는 다음과 예제와 같이 위의 조건을 모두 만족하므로 일급 객체이다.
// 1. 무명의 함수 리터럴로 생성
// 2. increase 변수에 저장
// -> 런타임 시점에 함수 리터럴이 평가되어 함수 객체가 생성되고 변수에 할당된다.
const increase = function (num) {
return ++num;
}
const decrease = function (num) {
return --num;
}
// 2. 함수는 객체에 저장할 수 있다.
const predicates = { increase, decrease }
// 3. 함수는 매개변수에게 함수를 전달할 수 있다.
function makeCount(predicates) {
let num = 0;
// 4. 함수의 반환값으로 사용할 수 있다
return function () {
num = predicate(num);
return num;
}
}
// 3. 함수의 매개변수에게 함수를 전달할 수 있다.
const increase = makeCounter(predicates.increase)
console.log(increase()) // 1
console.log(increase()) // 2
// 3. 함수의 매개변수에게 함수를 전달할 수 있다.
const decrease = makeCounter(predicates.decrease)
console.log(decrease()) // -1
console.log(decrease()) // -2
함수가 일급 객체라는 것은 함수를 객체와 동일하게 사용할 수 있다는 의미다. 객체는 값이므로 함수는 값과 동일하게 취급할 수 있다.
따라서 함수는 값을 사용할 수 있는 곳(변수 할당문, 객체의 프로퍼티 값, 배열의 요소, 함수 호출의 인수, 함수 반환문)이라면 어디서든지 리터럴로 정의할 수 있으며 런타임에 함수 객체로 평가된다.
일급 객체로서 함수가 가지는 가장 큰 특징은 일반 객체와 같이 함수의 매개변수에 전달할 수 있으며, 함수의 반환 값으로 사용할 수도 있다는 것이다. 이는 함수형 프로그래밍을 가능케 하는 자바스크립트의 장점 중 하나다.
일반 객체는 호출 할 수 없지만 함수 객체는 호출 할 수 있다. 함수 객체는 일반 객체에는없는 고유의 프로퍼티를 소유한다.
function square(number) {
return number * number;
}
console.dir(square);
function square(number) {
return number * number;
}
console.log(Object.getOwnPropertyDescriptors(square));
console.log(Object.getOwnPropertyDescriptor(square, '__proto__'));
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
argument, caller, length, name, prototype 프로퍼티는 함수 객체의 데이터 프로퍼티이다.
__proto__
는 접근자 프로퍼티이며, 함수객체 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티를 상속 받은 것을 알 수 있다.
함수 호출 시 전달된 인수들의 정보를 담고 있는 순회가능한(iterable) 유사 배열 객체이며, 함수 내부에서 지역 변수 처럼 사용된다.
arguments 프로퍼티는 현재 일부 브라우저에서 지원하고 있지만 ES3부터 표준에서 폐지 되었다.
따라서, Function.arguments와 같은 사용법은 권장되지 않으며 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체를 참조하도록 한다.
function multiply(x,y) {
console.log(arguments)
return x * y;
}
console.dir(multiply())
console.dir(multiply(1))
console.dir(multiply(1,2))
console.dir(multiply(1,2,3))
Symbol.iterator가 존재해야 스프레드 문법의 대상이 될 수 있다
for-of도 사용 가능
function sum() {
if (!arguments.length) return 0;
// arguments를 복사하여 새로운 배열을 만듬
var array = Array.prototype.slice.call(arguments);
return array.reduce(function (pre, cur) {
return pre + cur;
});
}
// ES6
function sum(...args) {
if (!args.length) return 0;
return args.reduce((pre, cur) => pre + cur);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
parameter의 개수
익명함수는 ES6이전에는 빈 문자열 값을 가졌으나, ES6부터 함수 객체를 가리키는 식별자를 값으로 갖는다.
// 기명 함수 표현식(named function expression)
var namedFunc = function multiply(a, b) {
return a * b;
};
// 익명 함수 표현식(anonymous function expression)
var anonymousFunc = function(a, b) {
return a * b;
};
console.log(namedFunc.name); // multiply
console.log(anonymousFunc.name); // ''
모든 객체는 [[prototype]]
이라는 내부 슬롯을 갖는다.
[[prototype]]
내부 슬롯은 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다.
prototype 프로퍼티는 생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유하는 프로퍼티다.
일반 객체와 생성자 함수로 호출할 수 없는 non-constructordpsms prototype 프로퍼티가 없다.