일급 객체와 JS 함수 뜯어보기

곽지욱·2024년 10월 15일

JS

목록 보기
9/11
post-thumbnail

일급 객체

일급객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.

일급객체란 구체적으론 다음과 같은 조건을 만족하는 객체를 일급 객체 라 한다.

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

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

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

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

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

다른 건 다 직관적으로 이해할 수 있겠지만, 헷갈릴 수 있는 1번 조건에 대해 알아보자

// 1. 무명의 리터럴로 생성 후 즉시 실행 (IIFE - 즉시 실행 함수 표현)
(function() {
  console.log('이 함수는 무명 리터럴로 런타임에 생성되고 바로 실행됩니다!');
})();
  • 위 코드는 함수를 function 키워드로 정의했지만 이름을 붙이지 않은 익명 함수 이다

  • 이 익명 함수는 정의와 동시에 즉시 실행(IIFE) 된다 이런 방식은 함수를 특정 시점에 런타임에서 직접 생성하고 바로 사용하고자 할 때 많이 활용된다.

  • 이런 방식은 함수를 특정 시점에 런타임 에서 직접 생성하고 바로 사용하고자 할 때 많이 활용된다.

  • 여기서 런타임에 생성 가능하다는 의미가 무엇이냐??

런타임은 프로그램이 실행 중일 때를 의미한다. 즉, 런타임에 생성 가능하다는 것은 프로그램이 실행되는 도중에 필요한 시점에 함수를 새로 생성하고 사용할 수 있는 뜻을 말한다.

런타임 생성의 차이

function sayHello() {
  console.log("Hello!");
}
sayHello();  // "Hello!" 출력
  • 이렇게 정적으로 함수를 선언한 경우, 프로그램이 시작되기 전에 미리 정의되는 것이다.

  • 다시 말하면 이 함수는 코드가 실행되기 전에 메모리에 올라가 공간을 차지하는 것


변수에 무명 함수 저장

const greet = function() {
  console.log("Hello, World!");
};
greet();  // "Hello, World!" 출력
  • 이 경우 익명함수를 프로그램이 실행되는 도중 즉, 런타임에 생성한다.

  • 함수를 정의한 코드가 실행될 때 비로소 메모리에 함수가 생성되고, 변수 greet 에 저장된다.


그래서 리터럴이란?

  • 리터럴이란 코드를 작성할 때 고정된 값 자체를 표현하는 방식을 말한다.

  • 프로그래밍 언어에서, 리터럴은 값을 직접 코드에 명시하는 것을 말한다.

즉, 함수 리터럴은 함수에 이름을 붙이지 않고, 곧 바로 코드에서 익명함수로 사용할 수 있는 것을 의미한다.


그래서 런타임 생성과 사용이 왜 유용한데?

  • 런타임에 함수를 생성한다는 것은 유연하게 함수 필요할 때 만들어 사용할 수 있다는 뜻을 말한다.

  • 이를 통해 코드가 동적으로 변경되는 상황에 대응할 수 있다, 예를 들어 클릭 이벤트가 발생할 때 마다 새로운 함수를 만들고 호출할 수 있는 것

document.getElementById('myButton').addEventListener('click', function() {
  console.log('버튼이 클릭되었습니다!');
});
  • 우리가 자주보는 이 문법은 사실 버튼 클릭 시 익명 함수를 즉석에서(런타임에) 생성하고 실행하는 것이다.

  • 미리 정의된 함수 없이 이벤트가 발생할 때 마다 필요한 함수를 동적으로 생성하기 때문에 메모리 관리의 효율성 또한 상승할 수 있는 것


함수의 전달

일급 객체로서 함수가 가지는 가장 큰 특징은 함수의 매개변수에 전달할 수 있으며, 함수의 반환 값으로 사용할 수 있다는 것이다.

이는 함수형 프로그래밍을 가능케 하는 자바스크립트의 장점 중 하나다

function repeatAction(n, action) {
  for (let i = 0; i < n; i++) {
    action();  // 전달된 함수 실행
  }
}

// 'Hello'를 3번 출력하는 익명 함수 전달
repeatAction(3, function() {
  console.log("Hello!");
});
  • 이처럼 함수를 매개변수로 전달해 특정 로직을 유연하게 적용하는 것이 가능 한 것.

함수 객체의 프로퍼티

브라우저 콘솔에서 console.dir 를 입력해서 함수 객체의 내부를 쉽게 들여다 볼 수 있다.

왜 함수 객체의 프로퍼티를 이해해야 할까?

  1. 함수도 객체이기 때문
  • 자바스크립트에서는 함수도 일급 객체로 취급 되기 때문이다. 이는 함수가 변수에 할당되거나, 다른 함수의 인자로 전달, 함수에서 반환될 수 있다는 의미이다.

  • 함수를 객체처럼 다룰 수 있기 때문에 프로퍼티와 메서드를 추가하거나 내장된 프로퍼티에 접근하는 것 또한 가능하기 때문.

function exampleFunction(a, b) {
  return a + b;
}

// 브라우저 콘솔에서 함수 객체의 내부를 확인
console.dir(exampleFunction);
ƒ exampleFunction(a, b)
  arguments: null
  caller: null
  length: 2
  name: "exampleFunction"
  prototype: {constructor: ƒ}
  [[FunctionLocation]]: script.js:1
  [[Scopes]]: Scopes[2]

console.dir 은 객체의 내부 구조를 트리 형태로 펼쳐 보여주는 것이다. 이를 통해 함수 객체의 여러 프로퍼티들을 확인할 수 있는 것!

argument 프로퍼티

함수 객체의 argument 프로퍼티 값은 함수 호출 시 전달 된 인수들의 정보를 담고 있는 argument 객체이다.

마치 배열 객체처럼 순회 가능하다는 특징을 가지고 있다. 하지만 진짜 배열은 아니기 대문에 map 이나 forEach 와 같은 배열 메서드를 직접 사용할 수는 없고 Array 로 변환해야 한다.

선언된 매개변수의 개수보다 인수를 적게 전달했을 경우 인수가 전달되지 않은 매개변수는 undefined 로 초기화된 상태이다

function example(a, b) {
  console.log("a:", a);  // 첫 번째 인수
  console.log("b:", b);  // 두 번째 인수
  console.log("arguments:", arguments);  // 모든 인수 출력

  // arguments 객체 순회
  for (let i = 0; i < arguments.length; i++) {
    console.log(`arguments[${i}]:`, arguments[i]);
  }
}

// 3개의 인수를 전달했지만 매개변수는 2개만 선언됨
example(1, 2, 3);
a: 1
b: 2
arguments: [1, 2, 3]
arguments[0]: 1
arguments[1]: 2
arguments[2]: 3
  1. 매개변수 a, b에는 전달된 첫 번째, 두 번째 인수가 각각 할당됩니다.

  2. 초과된 인수(여기서는 3)는 무시되지 않고 arguments 객체에 모두 담깁니다.

  3. arguments 객체를 순회하여 모든 전달된 인수를 확인할 수 있습니다.


사용자 정의 프로퍼티 추가 가능

  • 말했듯이 함수는 객체 이므로 사용자 정의 프로퍼티를 추가할 수 있다.
function greet() {
  console.log("Hello!");
}
greet.language = "Korean";

console.dir(greet);
console.log(greet.language); // 출력: Korean
  • 뿐만 아니라 [[Scope]] 같은 내부 정보도 확인할 수 있기 때문에 클로저를 이해하거나 디버깅할 때 유용하다

나머지 주요 프로퍼티

caller

  • 이 함수가 어디서 호출되었는지 참조한다. 현재 호출한 함수가 없을 경우 null

length

  • 함수가 기대하는 매개변수의 개수를 말한다. 위 예제에서는 두 개의 인수를 받기 때문에 2 이다.

name

  • 함수의 이름을 말한다. 익명 함수일 경우 anoymous 가 된다.

prototype

  • 함수가 생성자 함수로 사용될 때 새로 생성된 객체에 연결되는 프로토타입 객체를 말한다.

[Scopes]

  • 함수가 선언된 스코프 체인을 보여준다, 클로저를 사용한 경우 이 프로퍼티에서 클로저의 내부 상태를 확인할 수 있다.

0개의 댓글