JS and TS

타입스크립트 2

Eppo:) 2023. 5. 6. 13:54

04-1 함수 선언문

자바스크립트에서는 function 키워드로 만드는 함수 선언문과 => 키워드로 만드는 화살표 함수 두가지로 나뉘게 된다. 

function 함수이름(매개변수1, 매개변수2 [....]{
   함수 몸통 
}

타입스크립트 함수 선언문은 자바스크립트 함수 선언문의 매개변수와 함수 return type에 타입 주석을 붙이는 형태로 구성된다. 

function 함수이름(매개변수1 : 매개변수1타입, 매개변수2 : 배개변수2타입 [...]  : return 타입 {
  함수 몸통 
}

ex )                  
function  add( a :  number,  b : number ) :  number { return a+b }
                     매개변수
let result = add(1, 2) << 인수

매개변수와 반환값에 대한 타입주석은 생략할 수 있으나, 함수 구현의도를 파악하기 어렵기 때문에 추천하지 않는다. 


값을 반환하지 않는 함수는 반환타입이 void 가 된다.  return 타입이 없는 함수로 이해하면 좋다. 


변수처럼 함수도 타입이 있다.  함수 타입을 함수 시그니처라고 한다. 

(매개변수1타입, 매개변수 2타입 [...] ) => 반환타입 

ex)
let printMe : (string, number) => void = function (name : string, age: number) : void {
  함수 몸통 
}

매개변수가 없을 경우 () 로 표기,   () => void 는 매개변수도 없고, 리턴값도 없는 함수의 시그니처임 


타입스크립트에서는 타입별칭을 지원함.  type 키워드는 기존에 존재하는 타입을 이름만 바꿔서 사용할 수 있게 해준다 .

type 새로운 타입 = 기존 타입

예시)
// 문자와 숫자를 매개변수로 받아 리턴값이 발생되지 않는 함수를 지정하는 함수 시그니처에 
// stringNumberFunc 이름으로 타입 별칭을 부여 
type stringNumberFunc = (string, number) => void 

// 매개변수의 개수나 return 타입을 잘못 지정하는 것을 미연에 방치함 
let f : stringNumberFunc = function(a: string, b: number) : void { 함수몸통 }

// stringNumberFunc는 인자값이 두개인데 왜 없음? 이라는 에러 발생시킴 
let g : stringNumberFunc = function() : void {  }

 

undefined 는 모든 객체의 최하위 타입이기 때문에 어떤 타입이든 자식타입으로 간주하게됨 

interface INameable {
	name : string
}

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

let n = getName(undefined) // 오류 발생

console.log(n)

o.name 부분이 undefined.name 으로 인식하기 때문에 cannot read property 'name' of undefined  라는 오류를 발생

매개변수가 undefined 일 때의 예외처리를 고려해서 작성해야함 

interface INameable {
	name ?: string
}

function getName(o: INameable) { 
	return o != undefined && o.age ? o.age : 0
}

이렇게 지정하면 인자값이 undefined 거나 null 이거나 인자값을 넣지 않을 경우 0이라는 값을 리턴하게 해서 예외처리를 지정할 수 있음 


함수의 매개변수에 ? 을 붙이면 있어도 되고 없어도 되는 선택적 매개변수를 만들어낼 수 있음 위에 interface INameable을 참고 


04-2 표현식 

JS 는 함수형 언어 'scheme'과 'prototype'  기반 객체지향 언어 'self' 를 모델로 만들어짐 

객체지향언어와 함수형 언의 특징을 모두 가지고 있음. 

 

자바스크립트에서 함수는 function 클래스의 instance

let add = new function ('a', 'b', 'return a+b')
let result = add(1,2)

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

let add2 = function(a, b) { return a+b } // 함수 표현식

함수 표현식은 함수를 리터럴하는 형식으로 값이 존재한다는 것을 기억하기


프로그래밍 언어가 일등함수 기능을 제공하면 함수형 프로그미랭이라고 함 

일등함수는 함수와 변수를 구분하지 않는다는 의미 

위의 let add2 예제게 일등함수를 보여주는 대표적인 예시,  변수에 함수를 할당함 변수와 함수를 동일하게 인식한다는 의미


프로그래밍 언어에서 표현식이라는 용어는 리터럴/ 연산자 / 변수 / 함수호출 등이 복합적으로 구성된 코드 형태를 의미 

표현식은 항상 컴파일러에 의해 계산법이 적용되어 어떤 값으로 리턴한다는 것을 기억 

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

밑줄 쳐진 쟤가 함수 표현식,  저 함수는 뭔가를 지지고 볶아서 어떤 값을 리턴해 add2 변수에 넣어줌


컴파일러는 표현식을 만나면 계산법을 적용해서 어떤 값을 만들어냄 

컴파일러가 1+2 라는 표현식을 만나면 조급한 계산법을 적용해 3이라는 값을 만들고 

function(a, b) { return a+b }  이런 애들을 만나면 어떤 값이 들어올 지 모르기 때문에 값이 들어올 때까지 대기하는 느긋한 계산법을 사용함

어쨌든 결국에는 인자값으로 값이 지정될테니 조급한 계산법을 할것임 


어떤 변수가 함수 표현식을 담고 있다면  변수 이름 뒤에 함수 호출 연산자 () 를 붙여서 호출할 수 있음 

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

(a, b) {} ---> a와 b를 이용해서 몸통에 있는 함수를 호출할거야  


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

ESNext 자바스크립트와 타입스크립트는 function 키워드가 아닌 => 기호로 만드는 화살표 함수도 제공 

const 함수이름 = (매개변수1: 타입1, 매개변수2: 타입2[...]) : 반환타입 => 함수 몸통

화살표 함수는 몸통부분에 중괄호를 사용할 수도 있고 생략할 수도 있음 

const arrow1 = (a:number, b:number) => { return a + b } // 실행문 방식의 몸통 
const arrow2 = (a:number, b:number) => number => a + b  // 표현식 문 방식의 몸통

중괄호 사용 여부에 따라서 타입스크립트 문법이 동작하는 방식이 달라짐 


자바스크립트는 ESNext 이후부터 실행문과 표현식문을 동시에 지원( 타입스크립트 동일 ) , 이런 언어를 '다중 패러다임 언어(multi-paradigm language)' 이라고 함 

프로그래밍 언어에서 실행문은 CPU에서 실행되는 코드를 의미,  실행문은 CPU에서 실행만 될 뿐이지 결과를 알려주지 않는다. 따라서 실행문의 결과값을 얻기 위해서는 return  키워드를 사용해야함  

반면에 표현문은 CPU에서 실행된 결과를 굳이 return 키워드를 붙이지 않아도 결과값을 알려준다 


함수표현식은 대부분 언어에서 언급되는 익명함수의 다른 표현

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

 연산자 우선순위를 고려해서 코드를 분해해야함,  호출 연산자가 가장 순위가 높기 때문에 매개변수의 익명함수를 먼저 실행하고 1,2의 값을 대입해서 3의 결과를 도출 


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

let키워드는 변숫값이 변할 수 있기 때문에 지정한 function의 내용이 변질 될수 있어 const로 고정하는것이 좋음 


if와 같은 구문은 조건을 만족한 후 한줄의 실행문만 실행할때 중괄호를 생략해도 된다. 

복합실행문이라는 또다른 형태를 제공하기 위해서 위와 같은 설계를 허용하는 것, 복합실행문은 중괄호 안에 여러개의 실행문을 중첩해서 사용할 수 있는 형태 

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

function 키워드로 만드는 함수는 반드시 몸통을 중괄호로 감싸야 함. 여기서 중괄호는 복합실행문을 의미, 따라서 함수 몸통은 다음처럼 여러줄로 구현할 수 있다. 

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

실행문은 CPU에서 실행된 결과를 알려주지 않기 때문에 return 값을 꼭 지정해야한다. 

reutn 키워드는 반드시 함수 몸통에서 사용할 수 있다는 제약이 있다.

if(return x>0) x = 1
    ▴ 이렇게 쓰면 혼남

04-4 일등 함수 살펴보기 

일등 함수는 프로그래밍 언어가 제공하는 기능, 

일등함수 기능을 제공하는 언어에서 함수는 '함수표현식' 이라는 일종의 값을 의미 -> 함수의 인자로 사용할 수 있는 값으로 취급 

매개변수의 형태로 동작하는 함수를 콜백함수라고 함 

const f = (callkack: () => void): void => callback()

export const init = (callback : () => void) : void => {
	callback()
}

init 함수 매개변수로 실행하려는 익명함수를 전달, 저 익명함수가 콜백함수가 되는 것임 

인자값으로 전달된 함수는 init 함수 내부에서 마치 변수처럼 사용할 수 있음 


함수형 언어에서 함수는 변수에 담긴 함수 표현식이므로, 함수 안에 다른 함수를 중첩해서 구현할 수 있는데, 이것을 중첩함수라고 함 

const calc = (value: number, cd: (number) => void) : void => {
	let add = (a,b) => a+b
    function multiply(a, b){ reutrn a*b }
    
    let result = multiply(add(1,2), value)
    cd(result)
}

add랑 multiply 는 calc안에 정의된 함수, 함수안에 함수를 품고 있는 형태임 ㅇ_ㅇ 


고차함수는 또 다르 함수를 반환하는 함수를 말합니다. 

const add1 = (a:number, b:number) => a+b // 보통함수 
const add2 = (a:number):(number) => number => (b:number): number => a+b

const add2 = (a:number):(number) => number => (b:number): number => a+b

add 는 결국 a+b를 연산하는 함수를 리턴하는 것



위 내용을 타입별칭과 함수를 풀어서 설명하면 아래와 같음 

type NumberToNumberFunc = (number) => number

exrpot const add = (a: number) : NumberToNumberFunc => {
	//number를 리턴하는 NumberToNumberFunc 함수를 반환할거임
    const _add : NumberToNumberFunc = (b : number) : number => {
    	return a+b
    }
    return _add
}

결국 리턴하게 되는건 _add 

return a+b 이 부분이 고차함수와 연결된 클로저 라는 기능


04-5 함수 구현 기법 

선택적 매개변수는 항상 그 값이 undefined로 고정됨. 만약 함수 호출 시 인수를 전달하지 않더라도 매개변수에 어떤 값을 설정하로 싶다면 디폴트 매개변수로 해결할 수 있음 

(매개변수 : 타입 = 매개변수 기본값) 

type person = { name : string, age: number }

export 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 : 'Janme', age: 33}

age : number=10  이게 디폴트 매개변수