함수가 일급 객체라는것은 함수를 객체와 동일하게 사용 가능하다는 뜻이다. 객체는 값이고 함수도 값과 동일하게 취급 가능하다.
함수의 프로퍼티 어트리뷰트를 확인해 보자.
function x(y) {
return y * y
}
console.log(Object.getOwnPropertyDescriptors(x))
// {length: {…}, name: {…}, arguments: {…}, caller: {…}, prototype: {…}}
arguments
:
{value: null, writable: false, enumerable: false, configurable: false}
caller
:
{value: null, writable: false, enumerable: false, configurable: false}
length
:
{value: 1, writable: false, enumerable: false, configurable: true}
name
:
{value: 'x', writable: false, enumerable: false, configurable: true}
prototype
:
{value: {…}, writable: true, enumerable: false, configurable: false}
[[Prototype]]
:
Object
arguments,caller,length,name,prototype 프로퍼티는 일반 객체에는 없는 함수 객체 고유의 프로퍼티다.
하지만 __proto__는 접근자 프로퍼티며 함수 객체 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티를 상속받은걸 확인할 수 있다.
함수 호출 시 전달된 인수들의 정보를 담고있는 순회 가능한 유사 배열 객체며 함수 내부에서 지역 변수처럼 사용된다. 함수 외부에선 사용 불가.
function sum (x,y){
console.log(arguments)
return x + y
}
console.log(sum()) // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(sum(1,2)) // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(sum(1,2,3)) // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// arguments.length도 먹히므로 매개변수 갯수를 확정 할 수 없는 가변 인자 함수 구현할때 쓸 수 있음
// for(let i = 0 ; i < arguments.length; i++) 반복문 활용 가능
Symbol.iterator???
arguments 객체를 순회 가능한 자료구조인 이터러블로 만들기 위한 프로퍼티다.function multiply(x, y){ const iterato = arguments[Symbol.iterator]() console.log(iterator.next()) // {value: 1, done: false} console.log(iterator.next()) // {value: 2, done: false} console.log(iterator.next()) // {value: undefined, done: true} return x * y } multiply(1,2)
함수를 호출할 때 전달하는 인수가 불명확하고 인수 개수를 확인하고 그에 따라 함수의 동작을 다시 정의해야할때 arguments 객체가 쓰인다.
arguments 객체는 배열 형태로 인자 정보를 담고 있지만 유사 배열 객체다. 따라서 배열 메서드를 사용하지 못한다. Function.prototype.call, Faunction.prototype.apply를 사용해 간접 호출해야 한다.
// 함수에 매개 변수가 없다
function sum (){
let arr = Array.prototype.slice.call(arguments)
// 배열을 reduce 메소드를 이용하여 순회하며 즉시 실행 함수로 인자를 전부 더해준다.
return arr.reduce(function (pre, cur) {
return pre + cur
},0)
}
console.log(sum(1,2,3)) // 6
// Rest 파라미터로 쉽게 구현도 가능하다
function sum (...arr) {
return arr
}
console.log(sum(1,2,3)) // [1, 2, 3]
함수 객체의 length 프로퍼티는 함수를 정의할 때 선언한 매개변수의 개수를 가리킴.
// Rest 파라미터
function sum (...arr) {
return arr
}
console.log(sum(1,2,3)) // [1, 2, 3] 인수로 숫자 1,2,3를 넣음
sum.length // 0 Rest 파라미터는 개수로 안침
// 매개변수 배열
function sum (arr) {
return arr
}
console.log(sum([1,2,3])) // 배열을 집어 넣음
sum.length // 1 배열은 자체를 인자 하나로 침
arguments 객체의 length와 다른점은 arguments는 인자의 개수를 가르키고
함수 객체의 length 프로퍼티는 매개변수의 개수를 가르킨다.
name 프로퍼티는 함수 이름을 가르킨다. 함수를 호출할때 쓰는건 식별자로 호출하는 것이고 함수 이름은 다른거다.
// inden이라는 식별자에 함수이름 fun을 할당했다.
let inden = function fun() {}
console.log(inden.name) // fun 함수 이름을 리턴
console.log(fun.name) // fun is not defined 함수 이름으로 호출이 불가능하다
보통의 함수 선언문과 익명 함수 표현식은 식별자와 함수이름이 같다.
객체는 [Prototype]의 내부 슬롯을 갖는다. __proto__는 내부 슬롯이 가리키는 프로토타입 객체에 접근하기 위해 사용되는 접근자 프로퍼티다.
const obj = {x : 1, y : 2}
console.log(obj.__proto__ === Object.prototype) // true
console.log(obj.hasOwnProperty('y')) // true
hasOwnProperty메서드는 인수로 전달받은게 객체 고유의 프로퍼티 키일 경우에만 true 상속 받은 프로퍼티인 경우 false를 반환한다.
생성자 함수로 호출할 수 있는 함수 객체인 일반 함수와 생성자 함수가 소유하는 프로퍼티다.
일반 객체와 생성자 함수로 호출 불가능한 non-constructor에는 prototype 프로퍼티가 없다.