일급 객체
- 다음과 같은 조건을 만족하는 객체
- 무명의 리터럴로 생성할 수 있음 / 즉, 런타임에 생성이 가능함
- 변수나 자료구조(객체, 배열 등)에 저장할 수 있음
- 함수의 매개변수에 전달할 수 있음
- 함수의 반환값으로 사용할 수 있음
- 자바스크립트의 함수는 위 조건을 모두 만족하므로 일급 객체임
- 함수는객체이지만 일반 객체와는 차이가 있음
- 일반 객체는 호출할 수 없지만 함수 객체는 호출할 수 있음
- 함수 객체는 일반 객체에는 없는 함수 고유의 프로퍼티를 소유함
- '일급' 이란 뜻은 일급 시민 처럼 무슨 혜택을 받는 다는 뜻이 아니라, 사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻함
함수 객체의 프로퍼티
- 함수 객체의 내부
arguments
, caller
, length
, name
, prototype
프로퍼티는 모두 함수 객체의 데이터 프로퍼티임
__proto__
는 접근자 프로퍼티이며, 함수 객체 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티를 상속받는 것임
arguments 프로퍼티
- 함수 객체의 arguments 프로퍼티 값은 arguments 객체임
- arguments 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한(iterable) 유사 배열 객체이며 함수 내부에서 지역 변수처럼 사용됨
즉, 함수 외부에서는 참조할 수 없음
- 함수 객체의 arguments 프로퍼티는 현재 일부 브라우저에서 지원하고 있지만 ES3부터 표준에서 폐지됨
- 따라서
Function.arguments
와 같은 사용법은 권장되지 않음 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체를 참조하도록 함
- 자바스크립트는 함수의 매개변수와 인수의 개수가 일치하는지 확인하지 않음
- 따라서 함수 호출 시 매개 변수 개수만큼 인수를 전달하지 않아도 에러가 발생하지 않음
- 함수를 정의할 때 선언한 매개변수는 함수 몸체 내부에서 변수와 동일하게 취급됨
- 함수가 호출되면 함수 몸체 내에서 암묵적으로 매개변수가 선언되고 undefined로 초기화된 이후 인수가 할당 됨
- 선언된 매개변수의 개수보다 인수를 적개 전달했을 경우 인수가 전달되지 않은 매개변수는 undefined로 초기화된 상태를 유지하며 초과된 인수는 무시됨
- 그렇다고 초과된 인수가 그냥 버려지는 것은 아니고 모든 인수는 암묵적으로 arguments 객체의 프로퍼티로 보관됨
- 따라서 arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용함
function sum() {
let res = 0;
for (let i = 0; i < arguments.length; i++) {
res += arguments[i];
}
return res;
}
console.log(sum());
console.log(sum(1,2));
console.log(sum(1, 2, 3));
- 유사 배열 객체느 배열이 아니므로 배열 메서드를 사용할 경우 에러가 발생함
- 배열 메서드를 사용하려면
Function.prototype.call
, Function.prototype.apply
를 사용해 간접호출해야 하는 번거로움이 있음
- 이러한 번거로움을 해결하기 위해 ES6에서는 Rest 파라미터를 도입함
- Rest 파라미터의 도입으로 모던 자바스크립트에서는 arguments 객체의 중요성이 이전 같지는 않지만 언제나 ES6만 사용하지는 않을 수 있기 때문에 알아둘 필요가 있음
caller 프로퍼티
- caller 프로 퍼티는 ECMAScript 사양에 포함되지 않는 비표준 프로퍼티이며 이후 표준화될 예정도 없으므로 사용하지 말고 참고로만 알아둘 것
- 함수 객체의 caller 프로퍼티는 함수 자신을 호출한 함수를 가리킴
function foo(func) {
return func();
}
function bar() {
return 'caller': ' + bar.caller;
}
console.log(foo(bar));
console.log(bar());
length 프로퍼티
- 함수 객체의 length 프로퍼티는 함수를 정의할 때 선언한 매개변수의 개수를 가리킴
- arguments 객체의 length 프로퍼티와 함수 객체의 length 프로퍼티 값은 다를 수 있으므로 주의해야 함
- arguments 객체의 length 프로퍼티는 인자(argument)의 객수를 가리키고, 함수 객체의 length 프로퍼티는 매개 변수(parameter)의 개수를 가리킴
name 프로퍼티
- 함수 객체의 name 프로퍼티는 함수 이름을 나타냄
- ES5와 ES6에서 동작을 달리하므로 주의가 필요함
- 익명 함수 표현식의 경우 ES5에서 name 프로퍼티는 빈 문자열을 값으로 갖지만 ES6에서는 함수 객체를 가리키는 식별자를 값으로 가짐
__proto__
접근자 프로퍼티
- 모든 객체는
[[Prototype]]
이라는 내부 슬롯을 가짐
[[Prototype]]
내부 슬롯은 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킴
- 내부 슬롯에는 직접 접근할 수 없고 간접적인 접근 방법을 제공하는 경우에 한하여 접근할 수 있음
[[Prototype]]
내부 슬롯에도 직접 접근할 수 없으며 __proto__
접근자 프로퍼티를 통해 간접적으로 프로토타입 객체에 접근할 수 있음
const obj = { a: 1 };
console.log(obj.__proto__ === Object.prototype);
console.log(obj.hasOwnProperty('a'));
console.log(obj.hasOwnProperty('__proto__')
- hasOwnProperty 메서드는 이름에서 알 수 있듯이 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우에만 true를 반환하고 상속받은 프로토타입의 프로퍼티 키인 경우 false를 반환함
prototype 프로퍼티
- prototype 프로퍼티는 생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유하는 프로퍼티임
- 일반 객체와 생성자 함수로 호출할 수 없는 non-constructor에는 prototype 프로퍼티가 없음
(function () {}).hasOwnProperty('prototype');
({}).hasOwnProperty('prototype');
- prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킴
참고 자료