Skip to content

Latest commit

 

History

History
1040 lines (751 loc) · 37.8 KB

File metadata and controls

1040 lines (751 loc) · 37.8 KB

04장 함수와 메서드

Table of Contents
  • 04-1 함수 선언문 🔗
    • 함수 선언문 문법 🔗
    • 매개변수와 인수, 인자 🔗
    • 매개변수와 반환값의 타입 주석 생략 🔗
    • void 타입 🔗
    • 함수 시그니처 🔗
    • type 키워드로 타입 별칭 만들기 🔗
    • undefined 관련 주의 사항 🔗
    • 선택적 매개변수 🔗
  • 04-2 함수 표현식 🔗
    • 함수는 객체다 🔗
    • 일등 함수 🔗
    • 함수 표현식 🔗
    • 함수 호출 연산자 🔗
    • 익명 함수 🔗
    • const 키워드와 함수 표현식 🔗
  • 04-3 화살표 함수와 표현식 문 🔗
    • 실행문과 표현식 문 🔗
    • 복합 실행문 🔗
    • return 키워드 🔗
    • 표현식 문 스타일의 화살표 함수 구현 🔗
    • 표현식과 표현식 문의 차이 🔗
  • 04-4 일등 함수 살펴보기 🔗
    • 콜백 함수 🔗
    • 중첩 함수 🔗
    • 고차 함수와 클로저, 그리고 부분 함수 🔗
  • 04-5 함수 구현 기법 🔗
    • 매개변수 기본값 지정하기 🔗
    • 객체 생성 시 값을 생략할 수 있는 타입스크립트 구문 🔗
    • 객체를 반환하는 화살표 함수 만들기 🔗
    • 매개변수에 비구조화 할당문 사용하기 🔗
    • 색인 키와 값으로 객체 만들기 🔗
  • 04-6 클래스 메서드 🔗
    • function 함수와 this 키워드 🔗
    • 메서드 🔗
    • 클래스 메서드 구문 🔗
    • 정적 메서드 🔗
    • 메서드 체인 🔗

04-1 함수 선언문

함수 선언문 문법

Javascript에는 function 키워드로 만드는 함수와 =>로 만드는 함수 두가지가 있다.

  • function 키워드로 만드는 Javscript 함수 선언문
function 함수 이름(매개변수1, 매개변수2[, ...]) {
    함수 몸통
}
  • function 키워드로 만드는 Typescript 함수 선언문
function 함수 이름(매개변수1: 타입1, 매개변수2: 타입2[, ...]): 반환값 타입 {
    함수 몸통
}
  • Typescript 함수 선언문 예시
function add(a: number, b: number): number {
    return a + b;
}

매개변수와 인수, 인자

매개변수parameter라고 하며 argument인수 혹은 인자라고 한다.
매개변수는 함수 선언문에서 함수 이름 뒤 괄호 안에 선언하는 변수다.
인자는 선언한 함수를 호출할 때 전달하는 값을 의미한다.

  • 매개변수인자 예시
function add(a: number, b: number): number {
    return a + b;
}

let result = add(1, 2);
console.log(result); // 3

위의 예시에서 ab매개변수이고 전달한 12인자다.

매개변수와 반환값의 타입 주석 생략

함수 선언문에서도 매개변수와 반환값에 대한 타입 주석 생략이 가능하다.
하지만 변수와 달리 함수의 매개변수와 반환 타입을 생략하는 것은 바람직하지 않다.
타입이 생략되어 있으면 함수의 구현 의도를 알기 어렵고 잘못 사용하기 쉽다.

void 타입

값을 반환하지 않는 함수는 반환 타입이 void다.

  • void 반환 타입 예시
function printMe(name: string, age: number): void {
    console.log(`name: ${name}, age: ${age}`);
}

printMe('Jack', 32); // name: Jack, age: 32

void 타입은 함수의 반환 타입으로만 사용할 수 있다.

함수 시그니처

변수에 타입이 있듯이 함수에도 함수 시그니처(Function Signature)라는 타입이 존재한다.
함수 시그니처를 사용하면 매개변수 개수타입, 반환 타입잘못 선언하는 것을 방지할 수 있다.

  • 함수 시그니처 문법

함수 시그니처는 아래와 같은 문법으로 사용된다.

(매개변수1 타입, 매개변수2 타입,[, ...]) => 반환값 타입
  • 함수 시그니처 예시
let printMe: (string, number) => void = function (
    name: string,
    age: number
): void {
    console.log(`name: ${name}, age: ${age}`);
};

printMe('Jack', 32); // name: Jack, age: 32

printMe함수는 stringnumber 타입의 매개변수가 존재하며 반환 타입이 void다.
따라서 printMe함수 시그니처(string, number) => void가 된다.
매개변수가 없으면 ()로 표현된다. () => void는 매개변수와 반환값이 없는 함수 시그니처다.

type 키워드로 타입 별칭 만들기

Typescript는 type이라는 키워드를 제공한다.
type 키워드는 기존에 존재하는 타입이름만 바꾸어 사용할 수 있게 해준다.
타입 이름을 바꾸어 사용하는 기능을 타입 별칭(Type Alias)라고 한다.

  • 타입 별칭 문법
type 새로운 타입 = 기존 타입;
  • 타입 별칭 예시

함수 시그니처stirngNumberFunc이라는 이름으로 타입 별칭을 만든 예시다.

type stringNumberFunc = (string, number) => void;
let f: stringNumberFunc = function (a: string, b: number): void {};
let g: stringNumberFunc = function (c: string, d: number): void {};

stringNumberFunc 별칭을 이용해 fg타입 주석을 간단하게 붙일 수 있다.

undefined 관련 주의 사항

undefined 타입은 Typescript의 타입 계층도에서 최하위 타입이다.

  • undefined를 고려하지 않은 예시
interface INameable {
    name: string;
}

function getName(o: INameable) {
    return o.name;
}

let n = getName(undefined);
console.log(n);

getNameINameable 타입을 요구하지만 undefined를 넘기면 구문 오류가 발생하지 않는다.
undefined는 최하위 타입이므로 INamealbe을 상속하는 자식 타입으로 간주된다.
하지만 코드를 실행시켜보면 o.name 부분이 undefined.name이 되어 오류가 발생한다.
이런 오류를 방지하려면 매개변수가 undefined인지 판별하는 코드를 작성해야 한다.

  • undefined를 고려한 예시
interface INameable {
    name: string;
}

function getName(o: INameable) {
    return o != undefined ? o.name : 'Unknown name';
}

let n = getName(undefined);
console.log(n); // Unknown name
console.log(getName({ name: 'Jack' })); // Jack

getName함수에서 oundefined일 경우 Unknown name을 반환하도록 작성해 해결하였다.
만약 인터페이스에 선택 속성이 있다면 아래와 같이 구현해야한다.

interface IAgeable {
    age?: number;
}

function getAge(o: IAgeable) {
    return o != undefined && o.age ? o.age : 0;
}

console.log(getAge(undefined)); // 0
console.log(getAge(null)); // 0
console.log(getAge({ age: 32 })); // 32

인자로 받은 oundefined인지 확인하고 해당 속성 존재여부 까지 확인하여야 한다.

선택적 매개변수

선택 속성과 같이 함수의 매개변수도 선택적 매개변수(Optional Parameter) 사용이 가능하다.

  • 선택적 매개변수 문법
function fn(arg1: string, arg?: number): void {}
  • 선택적 매개변수 예시
function fn(arg1: string, arg?: number): void {
    console.log(`arg: ${arg}`);
}

fn('Hello', 1);
fn('Hello');

두번째 인자인 arg는 없어도 정상적으로 함수가 동작한다.

  • 선택적 매개변수가 있는 함수의 시그니처 예시
type OptionalArgFunc = (string, number?) => void;

선택적 매개변수가 있는 함수의 시그니처는 타입 뒤에 ?를 붙여 사용한다.

[🔝위로가기]  /  [🔙뒤로가기]

04-2 함수 표현식

함수는 객체다

Javascript는 함수형 언어 scheme과 프로토타입 기반 객체지향 언어 self를 모델로 만들어졌다.
따라서 Javascript는 객체지향 언어함수형 언어의 특징을 모두 가지고 있다.
Typescript 또한 Javascript의 이러한 특징을 모두 가지고 있다.

let add = new Function('a', 'b', 'return a + b');
let result = add(1, 2);
console.log(result); // 3

Javascript에서의 함수는 Function 클래스의 인스턴스다.
위의 코드를 add라는 객체가 함수로서 동작해 3이라는 결과물이 출력된다. add가 함수라면 일반적으로 아래와 같은 구문을 사용하였을 것이다.

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

하지만 Function("a", "b", "return a + b")와 같이 변수 선언문 형태로 함수를 구현하였다.
또한 add함수와 같은 기능을 하는 함수를 아래와 같이도 구현할 수 있다.

let add2 = function (a, b) {
    return a + b;
};
console.log(add2(1, 2)); // 3

함수 선언문에서 함수 이름을 제외한 function () { }함수 표현식이라고 한다.
함수 표현식은 함수형 언어의 핵심 기능이다.

일등 함수

프로그래밍 언어가 일등 함수를 제공하면 함수형 프로그래밍언어라고 한다.
Javascript와 Typescript는 일등 함수기능을 제공하므로 함수형 프로그래밍언어다.
일등 함수함수와 변수를 구분하지 않는다는 의미를 갖는다.

let f = function (a, b) {
    return a + b;
};
console.log(f(1, 2)); // 3

f = function (a, b) {
    return a - b;
};
console.log(f(1, 2)); // -1

위의 코드에서 flet 키워드가 앞에 있으므로 값이 저장가능한 변수다.
변수 f에는 a + b 형태의 함수 표현식을 저장하였다.
하지만 f는 변수이기 때문에 a - b 형태의 함수 표현식 또한 저장이 가능하다.
따라서 f변수인지 함수인지 구분할 수 없어 Javascript와 Typescript는 일등 함수를 제공한다.

함수 표현식

표현식이란?

표현식리터럴, 연산자, 변수, 함수 호출등이 복합적으로 구성된 코드 형태를 의미한다.
1 + 21이라는 리터럴2라는 리터럴+ 연산자로 구성된 표현식이다.
표현식은 항상 컴파일러에 의해 계산법이 적용되어 어떤 이 된다.

함수 표현식 예시

일등 함수 예시와 같이 function (a, b) { return a + b }와 같은 부분이 함수 표현식이다.

let f = function (a, b) {
    return a + b;
};

function (a, b) { return a + b } 함수 표현식은 변수 f값처럼 대입된다.

계산법

컴파일러는 표현식을 만나면 계산법을 적용해 어떠한 값을 만든다.
계산법에는 조급한 계산법느긋한 계산법 두 가지가 존재한다.
컴파일러가 1 + 2라는 표현식을 만나면 조급한 계산법을 적용해 3이라는 값을 만든다.
반대로 컴파일러가 함수 표현식을 만나면 느긋한 계산법을 적용한다.
function (a, b) { return a + b }같은 함수 표현식ab의 값을 알 수 없기 때문이다.

함수 호출 연산자

변수가 함수 표현식을 가지면 변수 이름 뒤에 함수 호출 연산자 ()를 붙여 호출할 수 있다.
함수 호출이란 함수 표현식의 몸통 구현 부분을 실행한다는 뜻이다.
만약 함수가 매개변수를 필요로 한다면 함수 호출 연산자 안에 명시할 수 있다.

  • 함수 호출 연산자 예시
let functionExpression = function (a, b) {
    return a + b;
};
let value = functionExpression(1, 2);
console.log(value); // 3

functionExpression 변수는 함수 표현식을 가지고 있다.
따라서 변수 이름 뒤에 함수 호출 연산자 (1, 2)를 붙여 함수 호출문을 사용할 수 있다.
컴파일러는 함수 호출문을 만나면 함수 표현식조급한 계산법을 적용해 으로 바꾼다.

익명 함수

함수 표현식은 대부분 언어에서 언급되는 익명 함수의 다른 표현이다.
Javascript에서는 아래와 같은 익명 함수 코드 또한 동작한다.

let value = (function (a, b) {
    return a + b;
})(1, 2);
console.log(value); // 3

익명 함수를 작성해 바로 함수 호출 연산자를 사용해 value 변수에 저장하였다.
익명 함수()로 감싸 익명 함수의 처음과 끝을 컴파일러가 알 수 있도록 하였다.
컴파일러는 익명 함수게으른 계산법을 적용하지만 바로 ()연산자를 만나 값을 만든다.

const 키워드와 함수 표현식

함수 표현식을 담는 변수는 let보다는 const 키워드로 선언하는 것이 바람직하다.

  • let 키워드를 사용한 함수 표현식
let f = () => {};
f();

f = () => {
    console.log('Hello');
};
f(); // Hello

let 키워드를 사용하면 값이 변할 수 있기때문에 위와 같이 작성하면 함수가 변경될 수 있다.

  • const 키워드를 사용한 함수 표현식
const f = () => {};

// Cannot assign to 'c' because it is a constant.
c = () => {
    console.log('Hello');
};

함수 표현식을 담는 변수를 const 키워드로 선언하면 함수의 내용이 변할 수 없다.

[🔝위로가기]  /  [🔙뒤로가기]

04-3 화살표 함수와 표현식 문

실행문과 표현식 문

ESNext는 function 키워드가 아닌 => 기호로 화살표 함수를 만들 수 있다.
화살표 함수function 키워드와 다르게 {}를 생략할 수도 있다.

  • 화살표 함수의 중괄호 생략 예시
const arrow1 = (a: number, b: number): number => {
    return a + b;
};
const arrow2 = (a: number, b: number): number => a + b;

{}의 생략 여부에 따라 Typescript 문법이 실행문 방식표현식 문 방식으로 달라진다.
프로그래밍 언어는 실행문 지향 언어표현식 지향 언어로 구분되어 왔다.
C가 대표적인 실행문 지향 언어이고, Scala가 대표적인 표현식 지향 언어다.
Javascript는 실행문 지향 언어지만 ESNext와 Typescript는 실행문과 표현식을 동시에 지원한다.
이런 실행문과 표현식을 동시에 지원하는 언어를 다중 패러다임 언어 라고 한다.

실행문

프로그래밍 언어에서 실행문은 CPU에서 실행되는 코드를 의미한다.
하지만 실행문은 CPU에서 실행만 될 뿐 결과를 알려주지 않는다.
실행문의 결과를 알려면 반드시 return 키워드를 사용해야 한다.

  • 실행문과 예시

변수에 값을 대입하는 것은 대표적인 실행문의 예시다.

let x;
x = 1;

x라는 변수를 선언하고 단순히 x 변수에 1이라는 값을 대입하는 것으로 충분하다.

표현식 문

표현식 문은 CPU에서 실행된 결과를 return 키워드를 사용하지 않아도 알려준다.

  • 표현식 문 예시
let x = 10;
if (x > 0) {
    x = 1;
}

위에서 x > 0 부분은 truefalse로 결과를 알려주지 않으면 if구문이 동작하지 않는다.
만약 프로그래밍 문법이 아래와 같다면 코드를 작성하기 번거로워질 것이다.

if (return x > 0) {
    x = 1
}

똑같이 CPU에서 실행되더라도 x > 0처럼 return 키워드 없이 결과를 반환하는 실행문이 필요하다.
이렇게 return 키워드 없이 결과를 반환하는 실행문을 표현식 문이라고 구분해 부른다.

복합 실행문

프로그래밍 언어의 if 같은 구문은 조건을 만족하면 한 줄의 실행문만 실행하는 형태로 설계한다.

if (조건식) {
    실행문;
}

이러한 설계가 가능한 이유는 복합 실행문이라는 또 다른 형태를 함께 제공하기 때문이다.
대부분의 언어에서 복합 실행문{}를 이용해 아래와 같이 표현한다.

if (조건문) {
    실행문1;
    실행문2;
}

복합 실행문은 컴파일러가 여러 개의 실행문한 개의 실행문 처럼 인식하게 한다.

함수와 복합 실행문

function 키워드로 만드는 함수는 반드시 {}로 감싸는 복합 실행문을 이용한다.
따라서 함수 몸통은 아래와 같이 여러줄로 구현할 수 있다.

function f() {
    let x = 1,
        y = 2;
    let result = x + y + 10;
}

복합 실행문은 변수의 유효 범위도 지역 범위로 제한한다.
따라서 아래와 같이 두 함수의 몸통에 동일한 이름의 변수가 있어도 문제가 없다.

function f() {
    let x = 1;
}
function g() {
    let x = 2;
}

return 키워드

실행문은 CPU에서 실행된 결과를 알려주지 않는다.
함수 몸통을 복합 실행문으로 구현한 아래 같은 함수는 값을 반환하지 않는다.

function isGreater(a: number, b: number): boolean {
    a > b;
}

실행문 기반 언어느 이러한 문제를 해결하기 위하여 return 키워드를 제공한다.

function isGreater(a: number, b: number): boolean {
    return a > b;
}

그러나 return 키워드는 반드시 함수 몸통에만 사용할 수 있다는 제약이 있다.
이런 제약은 문법을 잘못 이해해 아래와 같은 코드를 만드는 것을 방지하려는 의도다.

if (return x > 0) {
    x = 1;
}

표현식 문 스타일의 화살표 함수 구현

위의 isGreater 함수를 화살표 함수로 구현하면 아래와 같다.

const isGreater = (a: number, b: number): boolean => {
    return a > b;
};

또한 ESNext와 Typescript에서는 아래 같이 간단하게 구현할 수 있다.

const isGreater = (a: number, b: number): boolean => a > b;

이 코드는 함수 몸통이 { a > b }가 아니라 a > b로만 구현이 되었다.
즉 함수 몸통이 값을 반환하는 실행문인 표현식으로만 구현이 되어있다.
따라서 return 키워드 또한 생략되어 함수가 구현되었다.
return은 복합 실행문 안에서만 사용가능해 return a > b로만 작성하면 오류가 발생한다.

표현식과 표현식 문의 차이

아래의 코드에서 a > b와 같은 코드는 C언어 에서 표현식이라고 하였다.
따라서 그 이후에 만들어진 언어들도 C언어와 같은 의미로 표현식이라고 여겨진다.
따라서 C언어의 관점에서 실행문의 일부일 뿐 자체가 실행문은 아니다.

let a = 1,
    b = 0;
if (a > b) {
    console.log('a is greater than b');
}
const isGreater = (a: number, b: number): boolean => a > b;

반면에 표현식 지향 언어 관점에서 isGreater 함수의 a > b는 자체가 실행문이다.
결론적으로 표현식이라는 용어는 두 가지 형태로 사용된다.
표현식 문이라는 표현은 이 둘을 구분하고자 사용한다.

실행문을 만드는 세미콜론

C언어는 모든 문장이 반드시 ;로 끝나야만 정상적으로 작동한다.
C언어 구문을 참조해 만든 ES5 Javascript또한 모든 문장 끝에 ;가 있어야 한다.
반면에 ESNext와 Typescript에서는 ;을 생략해 코드를 작성할 수 있다.
Typescript에서는 관습적으로 표현식 문에는 ;붙이지 않는다.

[🔝위로가기]  /  [🔙뒤로가기]

04-4 일등 함수 살펴보기

콜백 함수

일등 함수(First-Class Function)은 프로그래밍 언어가 제공하는 기능이다.
일등 함수기능을 제공하는 언어에서 함수는 함수 표현식이라는 일종의 값이다.
이것은 함수 표현식을 매개변수로 받을 수 있다는 것을 의미한다.
매개변수 형태로 동작하는 함수콜백 함수(Callback Function)이라고 한다.

  • 콜백 함수 문법
const f = (callback: () => void): void => callback();

위의 코드에서 f함수에는 callback이라는 매개변수가 존재한다.
callback은 함수 몸통에서 함수로서 호출하게 된다.

  • 콜백 함수 예시
export const init = (callback: () => void): void => {
    console.log('default initialization finished.');
    callback();
    console.log('all initialization finished.');
};

위의 코드에서 init 함수는 callback 매개변수를 받고 몸통에서 호출한다.

import { init } from './CallbackFunction';

init(() => console.log('custom initialization finished.'));

실제 init 함수를 호출해 사용하는 부분이다.
익명 함수를 사용해 실행하려는 함수를 init 함수에 전달한다.
실행하면 아래와 같은 결과를 얻을 수 있다.

인자로 넘겨준 함수가 정상적으로 실행되어 출력되는 것을 볼 수 있다.

중첩 함수

함수형 언어에서 함수는 변수에 담긴 함수 표현식 이므로 함수에 함수를 중첩해 구현할 수 있다.
아래의 코드에서 calc 함수는 addmultiply라는 이름의 중첩 함수를 구현하고 있다.

  • 중첩 함수 예시
const calc = (value: number, cb: (number) => void): void => {
    let add = (a: number, b: number): number => a + b;
    function multiply(a: number, b: number): number {
        return a * b;
    }

    let result = multiply(add(1, 2), value);
    cb(result);
};

calc(30, (result: number): void => {
    console.log(`result is ${result}`);
}); // result is 90

calc 함수 내부에 add, multiply 함수를 작성해 calc함수 내부에서 사용할 수 있다.

고차 함수와 클로저, 그리고 부분 함수

고차 함수(High Order Function)은 또 다른 함수를 반환하는 함수를 의미한다.
함수형 언어에서 함수는 함수 표현식이라는 값이기 때문에 다른 함수를 반환할 수 있다.

  • 고차 함수 예시
const add = (a: number): ((number) => number) => (b: number): number => a + b;
const result = add(1)(2);
console.log(result); // 3

위의 예시에서 함수 호출 연산자를 2개 사용add(1)(2)와 같이 호출하였다.

  • 고차 함수 예시를 이해하기 쉽게 변경한 예시

number를 받아 number를 반환하는 함수 시그니처 NumberToNumberFunc 타입을 정의했다.

type NumberToNumberFunc = (number) => number;

NumberToNumberFunc 타입을 반환하는 add2함수를 정의하였다.

type NumberToNumberFunc = (number) => number;
const add2 = (a: number): NumberToNumberFunc => {
    // NumberToNumberFunc 타입의 함수 반환
};

중첩 함수를 이용해 add2함수의 반환값을 구현할 수 있다.

type NumberToNumberFunc = (number) => number;
const add2 = (a: number): NumberToNumberFunc => {
    const _add2: NumberToNumberFunc = (b: number): number => {
        // number 타입의 반환값
    };
    return _add2;
};

add2 함수가 반환하는 _add2NumberToNumberFunc 타입이다.
고차 함수는 이와 같이 중첩 함수를 반환할 수 있다.
추가적으로 _add2의 함수 몸통을 구현하면 add2라는 고차 함수가 완성된다.

type NumberToNumberFunc = (number) => number;
const add2 = (a: number): NumberToNumberFunc => {
    const _add2: NumberToNumberFunc = (b: number): number => {
        return a + b;
    };
    return _add2;
};

여기서 aadd2함수의 매개변수 이고 b_add2 함수의 매개변수다.
_add2의 관점에서 a는 외부에 선언된 변수다.
함수형 프로그래밍 언어에서 이런 형태를 클로저(closure)라고 한다.

let fn: NumberToNumberFunc = add2(1);
console.log(fn(2)); // 3
console.log(add2(1)(2)); // 3

add2 함수로 나온 값은 함수 표현식이므로 fn에 호출 연산자를 붙일 수 있다.
fn은 단순히 add2(1)을 저장하는 임시 변수의 역할만 한다.
임시변수를 사용하지 않는다면 add2(1)(2)와 같이 호출 연산자를 두 개 사용해야 한다.
add2(1)처럼 값이 아닌 함수부분 애플리케이션 또는 부분 적용 함수라고 한다.

[🔝위로가기]  /  [🔙뒤로가기]

04-5 함수 구현 기법

매개변수 기본값 지정하기

선택적 매개변수는 항상 값이 undefined로 고정이 된다.
함수 호출시 인자를 전달하지 않더라도 어떤 값을 설정하고 싶을때가 있을 것이다.
이런 상황에서 디폴트 매개변수(Default Parameter)를 이용할 수 있다.

  • 디폴트 매개변수 문법
(매개변수: 타입 = 매개변수 기본값)
  • 디폴트 매개변수 예시
export type Person = { name: string; age: number };

export const makePerson = (name: string, age: number = 10): Person => {
    const person = { name: name, age: age };
    return person;
};

console.log(makePerson('Jack')); // { name: 'Jack', age: 10 }
console.log(makePerson('Jane', 33)); // { name: 'Jane', age: 33 }

위의 코드에서 makePerson 함수는 호출시 인자에 age가 없다면 기본값으로 10을 설정한다.

객체 생성 시 값을 생략할 수 있는 타입스크립트 구문

Typescript는 매개변수의 이름과 같은 이름의 속성을 가진 객체를 만들 수 있다.
이때 속성값 부분을 생략할 수 있는 단축 구문을 제공한다.

export type Person = { name: string; age: number };

const makePerson = (name: string, age: number = 10): Person => {
    const person = { name, age };
    return person;
};

console.log(makePerson('Jack')); // { name: 'Jack', age: 10 }
console.log(makePerson('Jane', 33)); // { name: 'Jane', age: 33 }

person 객체 생성시 { name: name, age: age }가 아닌 { name, age }만 작성해도 동작한다.

객체를 반환하는 화살표 함수 만들기

화살표 함수에서 객체를 반환할때 아래와 같은 코드를 생각할 수 있다.

const makePerson = (name: string, age: number = 10): Person => {
    name, age;
};

위와 같이 구현하게 되면 컴파일러는 {}를 객체가 아닌 복합 실행문으로 해석한다.
따라서 컴파일러가 {}를 객체로 해석하도록 객체를 ()로 감싸주어야 한다.

export type Person = { name: string; age: number };

const makePerson = (name: string, age: number = 10): Person => ({ name, age });

console.log(makePerson('Jack')); // { name: 'Jack', age: 10 }
console.log(makePerson('Jane', 33)); // { name: 'Jane', age: 33 }

위와 같이 화살표 함수표현식을 사용해 조금더 간단한 구조의 함수를 만들 수 있다.

매개변수에 비구조화 할당문 사용하기

객체에 비구조화 할당문을 적용하는 것과 동일하게 함수의 매개변수에도 적용할 수 있다.

  • 함수의 매개변수에 비구조화 할당문 사용 예시
export type Person = { name: string; age: number };

const printPerson = ({ name, age }: Person): void =>
    console.log(`name: ${name}, age: ${age}`);

printPerson({ name: 'Jack', age: 32 }); // name: Jack, age: 32

함수의 매개변수도 변수이기 때문에 위와 같이 비구조화 할당문 적용이 가능하다.

색인 키와 값으로 객체 만들기

ESNext에서는 아래와 같은 코드를 작성할 수 있다.

const makeObject = (key, value) => ({ [key]: value });

이러한 코드는 객체의 속성 이름을 변수로 만들고자할 때 사용한다.
[key] 부분이 name이면 { name: value }의 형태로 객체를 생성한다.

  • 객체의 속성 이름을 변수로 만드는 예시
const makeObject = (key, value) => ({ [key]: value });
console.log(makeObject('name', 'Jack')); // { name: 'Jack' }
console.log(makeObject('firstName', 'Jane')); // { firstName: 'Jane' }

Typescript에서 { [key]: value } 형태의 타입을 색인 가능 타입이라고 한다.
아래와 같은 형태로 keyvalue를 이용해 색인 가능 타입을 명시한다.

  • Typescript의 색인 가능 타입 문법
type KeyType = {
    [key: string]: string;
};
  • 색인 가능 타입을 사용해 객체를 만드는 예시
type KeyValueType = {
    [key: string]: string;
};

const makeObject = (key: string, value: string): KeyValueType => ({
    [key]: value,
});
console.log(makeObject('name', 'Jack')); // { name: 'Jack' }
console.log(makeObject('firstName', 'Jane')); // { firstName: 'Jane' }

색인 가능 타입을 이용해 속성 이름만 다른 객체를 위와 같이 만들 수 있다.

[🔝위로가기]  /  [🔙뒤로가기]

04-6 클래스 메서드

function 함수와 this 키워드

function키워드 함수는 Function이라는 클래스의 인스턴스이고 객체다.
객체지향 언어에서 인스턴스는 this 키워드를 사용할 수 있다.

let add = new Function('a', 'b', 'return a + b');
let result = add(1, 2);
console.log(result); // 3

Typescript에서는 function 키워드로 만든 함수에는 this를 사용할 수 있다.
반면에 =>를 이용한 화살표 함수에서는 this를 사용할 수 없다.

  • function 키워드 함수와 화살표 함수의 this 차이 예시
function functionKeyword() {
    console.log(this);
}
const arrowFunction = () => console.log(this);

console.log('At function keyword');
functionKeyword();
console.log('At arrow function');
arrowFunction();
  • function 키워드 함수와 화살표 함수의 this 차이 출력 결과

아래와 같이 function 키워드로 생성한 this키워드에는 무언가가 있는 것을 볼 수 있다.
반면에 =>를 이용한 화살표 함수는 this가 비어있는 객체를 반환한다.

메서드

Typescript에서 메서드(Method)는 function으로 만든 함수 표현식을 담고 있는 속성이다.

  • 메서드 예시

아래의 코드에서 클래스 Avaluemethod라는 두 개의 속성을 갖는다.
value에는 값인 1을 설정하고 method() => void 타입의 함수 표현식을 설정한다.

class A {
    value: number = 1;
    method: () => void = function (): void {
        console.log(`value: ${this.value}`);
    };
}

method 함수 내부에서 this 키워드를 이용해 value를 참조할 수 있다.
아래와 같이 A 클래스를 new연산자로 생성하고 method를 호출했다.

let a: A = new A();
a.method(); // value: 1

value: number = 1과 같이 설정했으므로 this.value가 1이 된다.
따라서 method의 호출 결과는 value: 1과 같이 출력된다.

클래스 메서드 구문

위에서 작성한 A 클래스는 구현하기 번거롭고 가독성 또한 떨어진다.
Typescript는 클래스 속성 중 함수 표현식을 담는 속성function키워드를 생략할 수 있다.

  • 클래스 메서드 구문 예시
class B {
    constructor(public value: number = 1) {}
    method(): void {
        console.log(`value: ${this.value}`);
    }
}

let b: B = new B(2);
b.method(); // value: 2

function 키워드의 생략과 constructor 생성자 함수를 이용할 수 있다.
A 클래스와 동일하게 동작하지만 으로 더 간단한 B 클래스를 작성할 수 있다.

정적 메서드

클래스의 속성은 static을 속성 앞에 붙여 정적으로 만들 수 있다.
메서드 또한 속성이기 때문에 static 수정자를 붙여 정적 메서드를 만들 수 있다.

  • 정적 메서드 예시
class C {
    static whoAreYou(): string {
        return "I'm class C";
    }
}

class D {
    static whoAreYou(): string {
        return "I'm class D";
    }
}

console.log(C.whoAreYou()); // I'm class C
console.log(D.whoAreYou()); // I'm class D

위의 코드의 CD클래스는 같은 이름의 정적 메서드를 가지고 있다.
new 연산자를 이용해 인스턴스를 생성하지 않아도 정적 메서드이기 때문에 사용할 수 있다.

메서드 체인

jQuery와 같은 라이브러리는 아래 같이 객체의 메서드를 이어서 호출할 수 있다.
이러한 방식을 메서드 체인 (Method Chain)이라고 한다.

$('p1').css('color', 'red').slideUp(2000).slideDown(2000);

Typescript로 메서드 체인을 구현하기 위해서는 메서드가 항상 this반환해야 한다.

  • 메서드 체인 예시
class Calculator {
    constructor(public value: number = 0) {}
    add(value: number) {
        this.value += value;
        return this;
    }
    multiply(value: number) {
        this.value *= value;
        return this;
    }
}

let calc = new Calculator();
let result = calc.add(1).add(2).multiply(3).multiply(4).value;
console.log(result); // (0 + 1 + 2) * 3 * 4 = 36

Calculator라는 클래스를 구현하고 내부에 addmultiply 메서드를 구현했다.
addmultiply 메서드는 연산을하고 this를 반환한다.
반환된 this 객체를 이용해 메서드 체인을 사용해 값을 얻을 수 있다.

[🔝위로가기]  /  [🔙뒤로가기]