[Modern JS Deep Dive] CH18-함수와 일급 객체

Boo Sung Jun·2022년 7월 8일
1

JavaScript

목록 보기
10/27
post-thumbnail

Modern JavaScript Deep Dive 스터디 - CH18 함수와 일급 객체

참고 자료: ⟪모던 자바스크립트 Deep Dive⟫"(이웅모 지음,위키북스, 2020)


1. 일급 객체(first-class object)

  • 아래 조건을 만족하는 객체
    • 무명의 리터럴로 생성할 수 있음. 즉, 런타임에 생성이 가능
    • 변수나 자료구조(객체, 배열 등)에 저장 가능
    • 함수의 매객변수에 전달 가능
    • 함수의 반환값으로 사용 가능
  • 자바스크립트의 함수는 일급 객체
  • => 자바스크립트의 함수형 프로그래밍을 가능하게 해줌
    - 일반 객체와 같이 함수를 함수의 매개변수에 전달할 수 있음
    - 함수의 반환값으로 함수를 사용할 수 있음
  • 일반 객체는 호출할 수 없지만 함수 객체는 호출이 가능, 함수 객체는 고유의 프로퍼티를 소유

2. 함수 객체의 프로퍼티

  • 함수도 객체(object) -> 함수도 프로퍼티를 가질 수 있음
  • arguments, caller, length, name, prototype 프로퍼티는 일반 객체에는 없는 함수 객체 고유의 데이터 프로퍼티

1) arguments 프로퍼티

  • arguments 프로퍼티 값은 arguments 객체
  • arguments 객체는 함수 호출 시 전달된 인수(argument)들의 정보를 담고 있는 순회 가능한(iterable) 유사 배열 객체
  • 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체를 참조 -> 함수 외부에서는 사용 불가
function multiply(x, y) {
  console.log(arguments);
}

multiply(1, 2, 3);

  • 자바스크립트에서는 함수의 매개변수(parameter)와 인수(argument)의 개수가 일치하는지 확인하지 않는다 -> arguments는 매개변수 개수를 확정할 수 없는 가변 인자 함수 구현에 유용
    • arguments 객체는 기본적으로 length 프로퍼티를 지원
    • length는 인수(argument)의 개수
    • length 프로퍼티 를 사용할 수 있는 이유는 arguments 객체 가 유사 배열 객체(array-like object) 이기 때문
function sum() {
  let res = 0;

  // arguments 객체는 length 프로퍼티가 있는 유사 배열 객체이므로 for 문으로 순회할 수 있다.
  for (let i = 0; i < arguments.length; i++) {
    res += arguments[i];
  }

  return res;
}

console.log(sum());        // 0
console.log(sum(1, 2));    // 3
console.log(sum(1, 2, 3)); // 6
  • arguments 객체는 유사 배열 객체이지, 배열 그 자체는 아님 -> 열 메서드를 사용할 경우 에러가 발생
  • 이를 보완하기 위해 ES6 부터 Rest 파라미터가 도입

    Rest Parameter

// ES6 Rest parameter
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
function add(x, y) {
  return x + y;
}

add();
/*
add 함수 객체의 length : 2, 
arguments 객체의 length : 0
*/
add(1, 2);
/*
add 함수 객체의 length : 2, 
arguments 객체의 length : 2
*/
add(1, 2, 3, 4, 5);
/*
add 함수 객체의 length : 2,
arguments 객체의 length : 5
*/

2) caller 프로퍼티

  • CMAScript 사양에 포함되지 않은 비표준 프로퍼티
  • 이후 표준화될 예정도 없기 때문에 중요도 낮음
  • 함수 자신을 호출한 함수를 가리킴

3) length 프로퍼티

  • 함수를 정의할 때 선언한 매개변수의 개수를 가르킴

arguments 객체 length vs 함수 객체 length

arguments 객체의 length 프로퍼티 !== 함수 객체의 length 프로퍼티

  • argument 객체의 length 프로퍼티: 인수(argument)의 개수
  • 함수 객체의 length 프로퍼티: 매개변수(parameter)의 개수

4) name 프로퍼티

  • 함수 이름을 가리킴
  • ES6부터 정식 표준
// 기명 함수 표현식
var namedFunc = function foo() {};
console.log(namedFunc.name); // foo

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

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

5) proto 접근자 프로퍼티

  • [[Prototype]] 내부 슬롯이 가리키는 프로토타입 객체에 접근하기 위해 사용하는 접근자 프로퍼티

    [[Prototype]]

    • 모든 객체는 [[Prototype]] 내부 슬롯을 가짐
    • [[Prototype]] 내부 슬롯은 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킴
const obj = { a: 1 };

// 객체 리터럴 방식으로 생성한 객체의 프로토타입 객체는 Object.prototype이다.
console.log(obj.__proto__ === Object.prototype); // true

// 객체 리터럴 방식으로 생성한 객체는 프로토타입 객체인 Object.prototype의 프로퍼티를 상속받는다.
// hasOwnProperty 메서드는 Object.prototype의 메서드다.
console.log(obj.hasOwnProperty('a'));         // true
console.log(obj.hasOwnProperty('__proto__')); // false

6) prototype 프로퍼티

  • 생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유하는 프로퍼티
  • 일반 객체나 non-constructor 에는 prototype 프로퍼티가 없음
// 함수 객체는 prototype 프로퍼티를 소유한다.
(function () {}).hasOwnProperty('prototype'); // -> true

// 일반 객체는 prototype 프로퍼티를 소유하지 않는다.
({}).hasOwnProperty('prototype'); // -> false

0개의 댓글