[typescript] ch04 함수
ch04
함수
4.1. 함수 선언과 호출
기본 함수 예시
- 보통 실무에서는 반환 타입은 자동으로 추론되도록 함(리턴 타입을 명시 하지 않는 경우가 많음)
function add(a: number, b: number): number {
return a + b;
}
함수 선언 예시
// 이름을 붙인 함수
function greet(name: string) {
return "hello" + name;
}
// 함수 표현식
let greet = function (name: string) {
return "hello" + name;
};
// 화살표 함수 표현식
let greet = (name: string) => {
return "hello" + name;
};
// 화살표 함수 축약식
let greet = (name: string) => "hello" + name;
// 함수 생성자 - 사용하지 않는 것이 좋음
let greet = new Function("name", 'return "hello" + name');
용어 설명
- 매개변수(parameter) - 함수 선언의 일부이며 함수를 실행하는 데 필요한 데이터 조각 (정형 매개변수)
- 인수(argument) - 함수를 호출 할 때 전달해야 하는 데이터 조각 (실질 매개변수)
4.1.1. 선택적 매개변수와 기본 매개변수
?
를 이용하여 선택적 매개 변수를 사용할 수 있음
function log(message: string, userId?: string) {
let time = new Date().toLocalTimeString();
console.log(time, message, userId || "not signed in");
}
// 기본값을 지정할 수 있음. 데이터 타입은 자동으로 추론됨.
function log(message: string, userId = "not signed in") {
let time = new Date().toLocalTimeString();
console.log(time, message, userId);
}
타입에서 선택형 마크 ?
사용
- 보통 실무에서는 선택적 매개변수 보단 기본 매개변수를 사용하게 됨
type Context = {
appId?: string;
userId?: string;
};
참조 : call(열거형), apply (배열형)
this 를 전달하여 해당 함수 호출
참조 : bind
this 를 전달하여 새로운 함수를 생성
let person1 = {
name: "Jo",
};
let person2 = {
name: "Kim",
study: function () {
console.log(this.name + "이/가 공부를 하고 있습니다.");
},
};
person2.study(); // Kim이/가 공부를 하고 있습니다.
// bind()
let student = person2.study.bind(person1);
student(); // Jo이/가 공부를 하고 있습니다.
console.log(person1); // { name: 'Jo' }
console.log(person2); // { name: 'Kim', study: [Function: study] }
console.log(student); // [Function: bound study]
arguments
- 함수에 전달된 인수에 해당하는 Array 형태의 객체
- 유사배열은 보통의 배열과 형태는 같지만, 배열이 아니기 때문에 Array.prototype.join() 등의 배열의 메소드를 사용할 수 없다
function foo(a, b, c) {
console.log(arguments);
}
foo(1, 2, 3); // [Arguments] { '0': 1, '1': 2, '2': 3 }
4.1.4 this 의 타입
- 보통 클래스 메소드를 제외한 다른 모든 곳에서 this 사용을 금한다
- this의 타입을 보장하지 않기 때문 (이를 위해 명시적으로 지정 가능)
function fancyDate(this: Date) {
return `${this.getDate()} / ${this.getMonth()} / ${this.getYear()}`;
}
4.1.5. generator
- 함수명 앞에 붙은 별표(*)는 이 함수가 제너레이터 임을 의미
- 제너레이터를 호출하면 이터러블 반복자가(IterableIterator) 반환
- 제너레이터는 영구적으로 값을 생성할 수 있음
- 제너레이터는 yield 라는 키워드로 값을 방출
- 소비자가 다음 값을 다시 요청하기 전 까지는 실행을 중지
- while(true) 루프가 영원히 실행되다가 비정상 종료되는 현상이 발생되지 않음.
// 제너레이터
function* createNumbers(): IterableIterator<number> {
let n = 0;
while (n < 10) {
yield n++;
}
return 100;
}
let numbers = createNumbers();
console.log(numbers.next()); // { value: 0, done: false }
console.log(numbers.next()); // { value: 1, done: false }
console.log(numbers.next()); // { value: 2, done: false }
console.log(numbers.next()); // { value: 3, done: false }
console.log(numbers.next()); // { value: 4, done: false }
console.log(numbers.next()); // { value: 5, done: false }
console.log(numbers.next()); // { value: 6, done: false }
console.log(numbers.next()); // { value: 7, done: false }
console.log(numbers.next()); // { value: 8, done: false }
console.log(numbers.next()); // { value: 9, done: false }
console.log(numbers.next()); // { value: 100, done: true }
console.log(numbers.next()); // { value: undefined, done: true }
4.1.6. 반복자
- 이터러블(iterable) : Symbol.iterator 라는 프로퍼티(반복자를 반환하는 함수)를 가진 모든 객체
- 반복자(iterator) : next 라는 매소드(value, done 두 프로퍼티를 가진 객체를 반환)를 정의한 객체
https://runebook.dev/ko/docs/typescript/iterators-and-generators
- Symbol.iterator 속성에 대한 구현이있는 객체는 반복 가능한 것으로 간주 됩니다.
- Array , Map , Set , String , Int32Array , Uint32Array 등과 같은 일부 내장 유형 에는 이미 Symbol.iterator 속성이 구현되어 있습니다.
- 객체의 Symbol.iterator 함수는 반복 할 값 목록을 반환합니다.
Iterable interface
Iterable 은 위에 나열된 반복 가능한 유형을 사용하려는 경우 사용할 수있는 유형입니다. 다음은 예입니다.
function toArray<X>(xs: Iterable<X>): X[] {
return [...xs];
}
for-of, for-in
let list = [4, 5, 6];
for (let i in list) {
// 키 반환
console.log(i); // "0", "1", "2",
}
for (let i of list) {
// 값 반환
console.log(i); // 4, 5, 6
}
참조 : TypeScript :: 6. 반복기와 재생기
// 문자형 반복자 생성
// Iterable 을 구현해야 됨
class StringIterable implements Iterable<string> {
#strings: string[];
#currentIndex: number = 0;
constructor(strings: string[]) {
this.#strings = strings;
}
[Symbol.iterator](): Iterator<string> {
let that = this;
let currentIndex = that.#currentIndex,
length = that.#strings.length;
const iterator: Iterator<string> = {
next(): { value: string; done: boolean } {
const value = that.#strings[currentIndex];
const done = currentIndex == length;
currentIndex++;
return { value, done };
},
};
return iterator;
}
}
for (let value of new StringIterable(["hello", "world", "!"]))
console.log(value);
4.1.7. 호출 시그니처
- 함수 표현식 log 를 선언하면서 Log 타입임을 명시
- 매개변수, 반환타입 등은 사전에 지정 했기 때문에 별도 명시하지 않아도 됨. (c의 header(.h) 느낌)
type Log = (message: string, userId?: string) => void;
let log: Log = (message, userId = "not signed in") => {
let time = new Date().toISOString();
console.log(time, message, userId);
};
log("wow");
4.1.8. 문맥적 타입화
- times 를 호출할 때 함수 선언을 인라인으로 제공하면 인수로 전달하는 함수의 타입을 명시할 필요가 없다.
function times(f: (index: number) => void, n: number) {
for (let i = 0; i < n; i++) f(i);
}
times((n) => console.log(n), 4);
// function times(f: Function, n: number) {
// 위와 같이 함수를 지정해도 동작은 가능
// 하지만 함수의 형태를 지정하지 않아 warning 을 보여줌
// 'n' 매개 변수는 암시적으로 'any' 형식이지만, 사용량에서 더 나은 형식을 유추할 수 있습니다.ts(7044)
4.1.9. 오버로드 된 함수 타입
아래는 동일 함. 단축형 시그니처를 사용하는 것을 추천. 물론 복잡한 상황에서는 아래 것이 유용
// 단축형 호출 시그니처
type Log = (message: string, userId?: string) => void;
// 전체 호출 시그니처
type Log = {
(message: string, userId?: string): void;
};
- 타입스크립트는 선언한 순서대로 오버로드 수행
- 타입스크립트에서는 오버로드 된 함수 선언으로 제공하고, 입력 타입에 따라 달라지는 함수의 출력 타입은 정적 타입 시스템으로 각각 제공
- 오버로드를 사용할 때는 함수를 쉽게 구현할 수 있도록 가능한 한 구현의 시그니처를 특장하는 것이 좋다.
- 타입을 좁게(구체적으로) 유지하는 것이 어떻게 주어진 시그니처로 함수를 구현하는 데 도움을 줄까 생각 함이 좋음
type Reservation = { from: Date; to: Date; destination: string };
// 2가지 시그니처를 가지고 있음
type Reserve = {
(from: Date, to: Date, destination: string): Reservation;
(from: Date, destination: string): Reservation;
};
// 위에서 정의한 시그니처와 리턴 타입을 맞춰 주도록 한다
let r1: Reserve = (
from: Date,
toOrDestination: Date | string,
destination?: string
) => {
if (toOrDestination instanceof Date) {
return { from, to: toOrDestination, destination: destination || "" };
} else {
return { from, to: from, destination: destination || "" };
}
};
오버로드는 자연스럽게 브라우저 DOM API 에서 유용하게 활용됨
<a>
요소에 대응하는 HTMLAnchorElement<canvas>
요소에 대응하는 HTMLCanvasElement<table>
요소에 대응하는 HTMLTableElement
[광고] STEEM 개발자 커뮤니티에 참여 하시면, 다양한 혜택을 받을 수 있습니다.
@wonsama transfered 2 KRWP to @krwp.burn. voting percent : 87.35%, voting power : 15.47%, steem power : 1986237.39, STU KRW : 1200.
@wonsama staking status : 1793.429 KRWP
@wonsama limit for KRWP voting service : 1.793 KRWP (rate : 0.001)
What you sent : 2 KRWP
Refund balance : 0.207 KRWP [65073847 - cbb4360cc79e95bc8ab281e4a206793faa638544]
Upvoted! Thank you for supporting witness @jswit.
![default.jpg](https://steemitimages.com/640x0/https://cdn.steemitimages.com/DQmNwBDPMPvL1yaKWTYF4wxyUmxWiEJgAy1WZWTJyCha5wE/jswit_comment_initial.w320.jpg)