일급객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.
일급객체란 구체적으론 다음과 같은 조건을 만족하는 객체를 일급 객체 라 한다.
무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다.
변수나 자료구조(객체,배열 등)에 저장할 수 있다.
함수의 매개변수에 전달할 수 있다.
함수의 반환 값으로 사용할 수 있다.
자바스크립트의 함수는 위의 조건을 모두 만족하는 일급 객체이다.
다른 건 다 직관적으로 이해할 수 있겠지만, 헷갈릴 수 있는 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 를 입력해서 함수 객체의 내부를 쉽게 들여다 볼 수 있다.
왜 함수 객체의 프로퍼티를 이해해야 할까?
자바스크립트에서는 함수도 일급 객체로 취급 되기 때문이다. 이는 함수가 변수에 할당되거나, 다른 함수의 인자로 전달, 함수에서 반환될 수 있다는 의미이다.
함수를 객체처럼 다룰 수 있기 때문에 프로퍼티와 메서드를 추가하거나 내장된 프로퍼티에 접근하는 것 또한 가능하기 때문.
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 객체이다.
마치 배열 객체처럼 순회 가능하다는 특징을 가지고 있다. 하지만 진짜 배열은 아니기 대문에 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
매개변수 a, b에는 전달된 첫 번째, 두 번째 인수가 각각 할당됩니다.
초과된 인수(여기서는 3)는 무시되지 않고 arguments 객체에 모두 담깁니다.
arguments 객체를 순회하여 모든 전달된 인수를 확인할 수 있습니다.
객체 이므로 사용자 정의 프로퍼티를 추가할 수 있다.function greet() {
console.log("Hello!");
}
greet.language = "Korean";
console.dir(greet);
console.log(greet.language); // 출력: Korean
null2 이다.anoymous 가 된다.