[JS스터디] 18. 함수와 일급객체

2023. 5. 6. 01:48JavaScript

일급 객체

다음 네 조건을 모두 만족하는 객체는 일급객체이다.

1. 무명의 리터럴로 생성할 수 있다. = 런타임에 생성이 가능하다.

2. 변수나 자료구조(객체, 배열 등)에 저장할 수 있다.

3. 함수의 매개변수에 전달할 수 있다.

4. 함수의 반환 값으로 사용할 수 있다.

자바스크립트의 함수는 위의 조건을 모두 만족하므로 일급 객체이다.

→ 함수를 객체와 동일하게 사용할 수 있다.

→ 함수는 객체처럼 값이므로, 값을 사용할 수 있는 곳이라면 어디서든 함수를 리터럴로 정의할 수 있고, 런타임에 함수 객체로 평가된다.

function increase = function (num) {
    return ++num;
};
const auxs = { increase, decrease }; // 함수를 객체에 저장 가능

function makeCounter(func) {
    let num = 0;
    return function() { // 함수를 반환 값으로 사용 가능
        num = func(num);
        return num;
    };
}

const increaseFunc = makeCounter(auxs.increase); // 함수를 매개변수에 전달 가능

함수 객체의 프로퍼티

  • 함수도 객체로서 프로퍼티를 가질 수 있다.함수도 프로퍼티를 가질 수 있다.

  • 함수는 일반 객체의 프로퍼티 외에 일반 객체는 없는 프로퍼티도 가지고 있다.함수의 모든 프로퍼티의 프로퍼티어트리뷰트를 Object.getOwnPropertyDescriptors 메소드로 확인할 수 있다.

  • proto 접근자 프로퍼티는 함수 고유의 프로퍼티가 아닌, Object.prototype 객체의 프로퍼티를 상속받은 것이다. Object.prototype의 프로퍼티는 모든 객체가 상속받아 사용할 수 있으므로 proto 접근자 프로퍼티는 모든 객체가 사용할 수 있는 프로퍼티다.__proto__는 일반 함수의 프로퍼티가 아니다.__proto__는 Object.prototype 객체의 접근자 프로퍼티이다.

arguments 프로퍼티

자바스크립트는 함수의 매개변수와 인수의 개수가 일치하는지 확인하지 않는다.

매개변수는 함수 호출 시 함수 몸체 내부에서 암묵적으로 선언되고 undefined로 초기화된다.

따라서 인수를 더 적게 전달한 경우, 인수를 전달받지 못한 매개변수는 undefined 값을 유지하고,

인수를 더 많이 전달한 경우, 초과된 인수는 무시된다. (arguments 객체에는 보관된다.)


💡 arguments 객체

모든 인수는 암묵적으로 arguments 객체의 프로퍼티 값으로 보관된다.

arguments 객체의 키는 인수의 순서, 값은 전달받은 인수이다.

(참고 - arguments 객체의 Symbol.iterator 프로퍼티를 통해 arguments 객체를 이터러블로 만들 수 있다.)


매개변수와 인수의 개수가 맞는지 확인하지 않는 이러한 특성으로 인해 함수 내에서 인수의 개수를 확인하고 제어를 해야 할 필요가 있을 수 있다. 이 때 arguments 객체를 사용한다.

function sum() {
    let res = 0;
    for (let i = 0; i < arguments.length; i++) { // 전달받은 인수의 개수
        res += arguments[i];
    }
    return res;
}
console.log(sum()); //0
console.log(sum(1,2)); //3, 초과하여 전달하였지만 arguments에는 저장됨
console.log(sum(1,2,3)); //6, 초과하여 전달하였지만 arguments에는 저장됨

arguments객체는 배열과 유사한 형태로 인자 정보를 담고 있어 유사 배열 객체라고 한다.

유사 배열 객체: length 프로퍼티를 가지고, for문으로 순회할 수 있는 객체

ES6부터 순회 가능한 자료구조인 이터러블이기도 하다.

유사 배열 객체는 배열이 아니기 때문에 배열 메소드를 사용하려면 간접 호출을 해야 해서 과정이 번거롭다.

→ 이를 해결하기 위해 ES6에서 Rest 파라미터를 도입했다.

→ Rest 파라미터로 인해 arguments 객체의 중요성은 🔽

function sum(...args) {
    return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1,2)); //3
console.log(sum(1,2,3,4,5)); //15

caller 프로퍼티

length 프로퍼티

: 함수 정의할 때 선언한 매개변수의 개수

주의 - arguments 객체의 length 프로퍼티와 값이 다를 수 있다. 매개변수의 개수와 인수의 개수가 다를 수 있기 때문이다.

name 프로퍼티

: 함수 이름

ES6부터 정식 표준, 이전과 동작을 달리함.

// 익명 함수 표현식
var anonymousFunc = function() {};
// ES5 - name 프로퍼티 값: 빈 문자열
// ES6 - name 프로퍼티 값: 함수 객체를 가리키는 변수 이름
console.log(anonymousFunc.name); // anonymousFunc

// 함수 선언문
function bar() {};
console.log(bar.name); // bar

함수 이름함수 객체를 가리키는 식별자는 의미가 다르다.

함수를 호출할 때는 함수 이름이 아닌 함수 객체를 가리키는 식별자로 호출한다.

proto 접근자 프로퍼티

[[Prototype]] 내부 슬롯: 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체. 모든 객체가 갖는다.

이에 접근하기 위해 proto 접근자 프로퍼티를 사용한다. (간접적으로 접근하는 방식)

const obj = { a: 1 };
console.log(obj.__proto__ === Object.prototype); //true

prototype 프로퍼티

: constructor (생성자 함수로 호출할 수 있는 함수 객체)만이 갖는 프로퍼티.

: 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킨다.

 


스터디 교재

18장 함수와 일급객체