Function(함수)
Function(함수)는 특정 작업을 수행하기 위한 코드의 블록이다. 함수는 특정한 입력 (인자)을 받아들이고, 그 입력에 따라서 일련의 계산을 수행한 뒤, 그 결과를 반환할 수 있다. 함수는 모듈화된 코드를 작성할 때 매우 유용하다.
함수는 함수의 인자와 반환 값의 타입을 명시할 수 있다. 이를 통해 함수의 사용자는 함수가 어떤 형태의 인자를 받고, 어떤 형태의 값을 반환하는지 미리 예측할 수 있으며, 이를 기반으로 코드를 작성할 수 있다. 함수의 인자와 반환 값의 타입 명시는 함수를 사용하는 코드의 안정성을 높여준다.
함수의 타입 명시는 함수 선언문 또는 함수 표현식에서 가능하다. 함수 선언문은 함수 이름과 함수 인자를 명시하여 함수를 정의하는 것이며, 함수 표현식은 함수를 변수에 할당하는 형태이다.
// 함수 선언문
function addNumbers(num1: number, num2: number): number {
return num1 + num2;
}
// 함수 표현식
const subtractNumbers = function(num1: number, num2: number): number {
return num1 - num2;
};
// 함수 사용
const sum = addNumbers(1, 2); // sum = 3
const difference = subtractNumbers(3, 2); // difference = 1
위 예시에서 addNumbers와 subtractNumbers 함수는 각각 숫자 두 개를 받아들이고, 두 숫자를 더하거나 빼서 결과를 반환한다.
함수의 인자와 반환 값의 타입이 모두 number로 명시되어 있다. 이를 통해 함수를 사용하는 코드는 이 함수들이 항상 number를 반환할 것이며, number 타입의 인자를 받을 것임을 미리 예측할 수 있다.
Function Type(함수 타입)
Function Type(함수 타입)은 함수가 어떤 형태의 인자를 받아들이고, 어떤 형태의 값을 반환하는지 명시하는 방법이다.
함수 타입은 함수의 인자와 반환 값의 타입을 정의하기 위해 () 안에 인자의 타입을 콤마로 구분하여 나열하고, => 기호 뒤에 반환 값의 타입을 명시한다. 이를 통해 TypeScript는 함수가 올바른 타입의 인자를 받고, 올바른 타입의 값을 반환하는지 확인할 수 있다.
type AddFunctionType = (num1: number, num2: number) => number;
const addNumbers: AddFunctionType = function(num1: number, num2: number): number {
return num1 + num2;
};
위 예시에서 AddFunctionType은 (num1: number, num2: number) => number 형태로 정의되어 있다.
이는 숫자 두 개를 인자로 받아들이고, 숫자를 반환하는 함수 타입이다. addNumbers 함수는 AddFunctionType을 준수하도록 정의되어 있으며, 따라서 addNumbers 함수는 숫자 두 개를 받아들이고, 숫자를 반환한다.
함수 타입은 인터페이스에서도 사용할 수 있다. 인터페이스에서 함수 타입을 정의하면, 해당 인터페이스를 구현하는 클래스나 객체는 해당 함수를 반드시 구현해야 한다.
interface Calculator {
add: (num1: number, num2: number) => number;
subtract: (num1: number, num2: number) => number;
}
class BasicCalculator implements Calculator {
add(num1: number, num2: number) {
return num1 + num2;
}
subtract(num1: number, num2: number) {
return num1 - num2;
}
}
위 예시에서 Calculator 인터페이스는 add와 subtract 함수를 정의하고 있다.
BasicCalculator 클래스는 Calculator 인터페이스를 구현하도록 정의되어 있으며, add와 subtract 함수를 반드시 구현해야 한다. 함수 타입을 인터페이스에서 정의함으로써, Calculator 인터페이스를 구현하는 클래스나 객체가 해당 함수를 반드시 구현하도록 강제할 수 있다.
Optional Parameters(선택적 매개변수)
Optional Parameters(선택적 매개변수)는 TypeScript에서 함수 정의 시 인자를 선택적으로 만들 수 있는 방법이다.
Optional Parameters를 사용하면 함수에 전달되는 인자 중 일부를 생략할 수 있다. 이 때 인자를 정의할 때 ? 기호를 사용한다. 즉, 매개변수이름?으로 매개변수를 선언할 수 있다. 이렇게 선언된 매개변수는 함수가 호출될 때 전달되지 않을 수 있으며, 이 경우 해당 매개변수는 undefined 값을 가진다.
function printName(firstName: string, lastName?: string) {
if (lastName) {
console.log(firstName + ' ' + lastName);
} else {
console.log(firstName);
}
}
printName('John'); // "John"
printName('John', 'Doe'); // "John Doe"
위 예시에서 printName 함수는 firstName과 lastName 매개변수를 가지고 있다.
lastName 매개변수는 ? 기호를 사용하여 선택적으로 선언되어 있다. 이렇게 하면 printName 함수를 호출할 때 lastName 인자를 생략할 수 있다. 만약 lastName 인자가 전달되지 않으면, lastName 매개변수의 값은 undefined가 된다.
Optional Parameters는 함수가 호출될 때 일부 인자를 생략하고 싶은 경우 유용하다. 함수 정의 시 필수적으로 지정해야 하는 인자와 선택적으로 지정할 수 있는 인자를 함께 사용할 수 있다.
다만, Optional Parameters를 남용하면 함수의 호출 방식이 복잡해지고 가독성이 떨어질 수 있으므로, 사용에 주의가 필요하다.
Default Parameters(기본 매개변수)
Default Parameters(기본 매개변수)는 TypeScript에서 함수 정의 시 매개변수에 기본 값을 지정하는 방법이다.
Default Parameters를 사용하면 함수를 호출할 때 인자를 생략하거나 undefined를 전달하더라도 기본값이 사용되어 함수가 실행된다. 이렇게 하면 함수를 호출할 때 일부 매개변수를 생략할 수 있으며, 생략한 매개변수에 대해서는 기본값이 적용되어 함수를 실행할 수 있다.
function greet(name: string = 'Guest', message: string = 'Hello') {
console.log(`${message}, ${name}!`);
}
greet(); // "Hello, Guest!"
greet('John'); // "Hello, John!"
greet('Jane', 'Hi'); // "Hi, Jane!"
위 예시에서 greet 함수는 name과 message 매개변수를 가지고 있다. 이 두 매개변수는 각각 Guest와 Hello로 초기화되어 있으며, 이 값은 인자가 전달되지 않을 때 기본값으로 사용된다.
Default Parameters를 사용하면 함수 정의 시에 더욱 간결하고 유연한 코드를 작성할 수 있다. 하지만 이러한 기능은 매개변수의 기본값이 매우 간단한 경우에만 사용하는 것이 좋다.
너무 복잡한 기본값을 설정하면 코드를 이해하기 어렵고 유지보수가 어려워질 수 있다.
Rest Parameters(나머지 매개변수)
Rest Parameters(나머지 매개변수)는 TypeScript에서 함수 정의 시 인자를 배열로 받는 방법이다.
Rest Parameters를 사용하면 함수를 호출할 때 인자의 개수에 제한을 받지 않고 배열 형태로 인자를 전달할 수 있다. 이 때 함수 정의 시 Rest Parameters로 선언된 매개변수는 함수 내부에서 배열로 처리된다.
function sum(...numbers: number[]) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum()); // 0
console.log(sum(1)); // 1
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3)); // 6
위 예시에서 sum 함수는 Rest Parameters를 사용하여 numbers 배열을 받도록 정의되어 있다.
이렇게 하면 함수를 호출할 때 전달되는 모든 인자가 numbers 배열의 요소로 처리된다. 따라서 sum 함수 내부에서는 numbers 배열을 reduce 함수를 사용하여 모든 요소의 합을 계산하고 반환한다.
Rest Parameters는 함수를 호출할 때 인자의 개수에 제한을 받지 않고 유연하게 처리할 수 있도록 해준다. 함수 내부에서 Rest Parameters로 전달된 인자는 배열로 처리되므로, 배열에 대한 다양한 메소드를 사용하여 인자를 처리할 수 있다.
Overloads(오버로드)
Overloads(오버로드)는 TypeScript에서 함수를 다양한 인자 형태로 호출할 수 있도록 지원하는 기능이다.
Overloads를 사용하면 함수에 전달되는 인자의 타입, 개수, 반환값 등에 따라서 함수의 동작을 다르게 설정할 수 있다. 이렇게 하면 동일한 함수 이름을 사용하면서 다양한 인자 형태를 처리할 수 있어 코드의 가독성과 유지보수성이 좋아진다.
function addItem(item: string): void;
function addItem(quantity: number, item: string): void;
function addItem(quantityOrItem: number | string, item?: string): void {
if (typeof quantityOrItem === 'string') {
console.log(`Added 1 ${quantityOrItem}.`);
} else {
console.log(`Added ${quantityOrItem} ${item}.`);
}
}
addItem('apple'); // "Added 1 apple."
addItem(2, 'oranges'); // "Added 2 oranges."
위 예시에서 addItem 함수는 Overloads를 사용하여 string 형태의 인자 1개, number와 string 형태의 인자 2개를 받도록 정의되어 있다. 이렇게 하면 addItem 함수를 호출할 때 전달되는 인자에 따라서 동작이 달라지도록 설정된다.
Overloads를 사용하면 함수의 인자 형태에 따라서 함수 내부에서 처리하는 코드를 다르게 설정할 수 있다. 이러한 기능은 코드의 가독성과 유지보수성을 높이는 데 매우 유용하다.
하지만 Overloads를 사용할 때는 함수의 인자 형태가 명확하게 구분되어야 하며, 함수의 인자 개수가 많아질수록 코드가 복잡해질 수 있다.
Function This(함수 내부에서의 this)
Function This(함수 내부에서의 this)는 JavaScript와 TypeScript에서 함수를 호출할 때 어떤 객체가 함수를 호출했는지를 가리키는 특별한 객체이다.
Function This는 함수를 호출한 객체가 존재하지 않는 경우에는 전역 객체를 가리키게 된다. 이 때 전역 객체는 브라우저에서는 window 객체, Node.js에서는 global 객체를 의미한다.
하지만 Function This의 값은 함수를 호출하는 방식에 따라서 달라진다. 예를 들어 함수를 객체의 메소드로 호출한 경우, Function This는 해당 객체를 가리킨다. 또한 함수를 call, apply, bind 메소드를 사용하여 호출할 경우, Function This는 해당 메소드에 전달한 인자 중 첫 번째 인자를 가리킨다.
TypeScript에서는 함수 내부에서 this를 사용할 때 this의 타입을 명시적으로 지정할 수 있다. 이 때 this의 타입은 function 키워드와 함수 이름 사이에 this 키워드를 사용하여 명시할 수 있다.
function greet(this: { name: string }, message: string): void {
console.log(`${this.name} says: ${message}`);
}
const person = { name: 'John' };
greet.call(person, 'Hello, world!'); // "John says: Hello, world!"
위 예시에서 greet 함수는 this의 타입을 { name: string }로 지정하고 있다.
이렇게 하면 greet 함수 내부에서 this.name을 사용할 때 name 속성이 존재하는 객체만을 대상으로 사용할 수 있다. 따라서 greet 함수를 호출할 때 call 메소드를 사용하여 person 객체를 this로 전달하면 person 객체의 name 속성을 출력할 수 있다.
Function This는 JavaScript와 TypeScript에서 함수의 동작을 결정하는 중요한 요소 중 하나이다. 이러한 특성 때문에 Function This는 함수를 사용하는 과정에서 유의할 필요가 있다.