[Typescript] 복습 - (3)

yongkini ·2023년 2월 16일
0

TypeScript

목록 보기
11/11

함수 표현식

JS에서 함수는 클래스의(Function 클래스) 인스턴스다

: 이 말을 약간 풀어서 말해보면 js의 함수는 우리가 객체 지향 프로그래밍에서 특정 클래스에서 인스턴스를 생성하면, 그 인스턴스는 해당 클래스에 정의된 특성 및 메서드를 실행할 수 있는 자격 등을 갖게되는 것처럼, 함수도 Function(같은 말이지만) 클래스의 인스턴스 이기에 Function class 내의 속성과 기능 등을 쓸 수 있는 자격을 얻게 된다. 객체 지향 언어와 함수형 언어의 특징을 모두 갖는 JS 는 Function Class 로 만든 함수를 바탕으로 함수형 프로그래밍도 할 수 있는 것이다.

함수형 언어란 뭘까

: 함수형 언어의 핵심 기능을 통해서 함수형 언어에 대해 알아보면, 가장 중요한 것이 '함수 표현식'이다. JS 개발자라면 많이 들어봤을 함수 표현식은 대략적으로 풀어 말해보면 함수를 변수에 선언할 때 쓰는 코드를 말한다. 예를 들어,

const func1 = function(a,b) { return a - b; }

위와 같이 const로 선언 및 할당해준 func1 에 초기화 해준 값이 함수인데, 이 함수를 '함수 표현식'이라고 한다. 정확히는

function(a,b) { return a - b; }

위와 같은 코드를 함수 표현식이라고 한다. 이러한 함수 표현식은 함수형 언어의 핵심이다. 좀 더 정리해보면, 프로그래밍 언어가 '일등 함수' 기능을 제공하면 '함수형 프로그래밍 언어'라고 한다. JS와 TS는 일등 함수 기능이 있으므로 함수형 프로그래밍 언어라고 한다.

그럼 또 일등 함수는 뭔가

: 의미는 함수와 변수를 구분하지 않는다 이다. 함수와 변수를 구부하지 않는다? 즉, 함수와 변수가 위에서 보여진 것처럼 다를게 없다는 것이다. 본래 함수형 프로그래밍 언어가 아니라면

function func1 (a,b) { return a - b; }

위의 func1 은 위와 같이 정의돼야 한다. 즉, 변수 선언문으로 쓰여질게 아니라 위와 같이 정의돼야 함수형 프로그래밍 언어가 아닌 것이다. 하지만 위에서 말한 것처럼 JS, TS는 아래와 같은 선언문 형태로도 함수를 정의할 수 있다.

const func1 = function(a,b) { return a - b; }

이런 부분에 있어서 변수와 함수의 차이가 없기에 이러한 함수형 프로그래밍 언어에서 함수를 일등 함수라고 한다(변수와 함수의 차이가 없다).

표현식에 대해서 좀 더 자세히 알아보기

: 프로그래밍 언어에서 표현식은 리터럴, 연산자, 변수, 함수 호출 등이 복합적으로 구성된 코드 형태를 의미한다. 또한, 표현식은 컴파일러에 의해 어떤 계산법이 적용돼 특정한 값이 된다. 예를 들어, 1 + 2라는 표현식은 컴파일러에 의해 3이된다.

** 리터럴
: 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다. 예를 들어, 개발자가 3을 입력하면 자바스크립트 엔진은 이를 평가해 숫자 값 3을 생성한다.
ex) 3 // 숫자 리터럴 3
이처럼 리터럴은 사람이 이해할 수 있는 문자(아라비아 숫자, 알파벳, 한글 등) 또는 미리 약속된 기호('', "", ., [], {} 등)로 표기한 코드이다. 자바스크립트 엔진은 코드가 실행되는 시점인 런타임에 리터럴을 평가해 값을 생성한다. 즉, 리터럴은 값을 생성하기 위해 미리 약속한 표기법이라고 할 수 있다. 이에 따라, 리터럴을 사용하면 다양한 종류의 값을 생성할 수 있다. (data type)

값으로 평가될 수 있는 문은 모두 표현식이다.
ex) var count = 10;
식별자 참조는 값을 생성하지는 않지만 값으로 평가되므로 표현식이다.
ex) count // 10

: 그렇다면 계산법은 뭘까? 컴파일러는 표현식을 만나면 계산법을 적용해 어떤 값을 만든다. 이 때, 계산법에는 조급한 계산법과 느긋한(혹은 지연) 계산법 두 가지가 있는데, 예를 들어, 조급한 계산법으로 1 + 2를 만나면 컴파일러가 3을 만드는 계산법이 이에 해당된다. 이와 달리, 느긋한 계산법은 function(a,b) { return a+b }라는 함수 표현식을 만났을 때 a+b가 뭔지 아직 몰라서(매개변수) 느긋한 계산법을 통해 지연 후 결과값을 내게 되는걸 말한다.

함수 표현식이 컴파일러에 의해 계산될 때 느긋한 계산법 -> 조급한 계산법으로 바뀌어서 결과가 산출되는 과정

const func1 = function (a,b) { return a+b; } 
// 여기까지 컴파일러가 읽었을 땐 a,b에 어떤 값이 들어갈줄 모르기 때문에 느긋한 계산법으로 일종의 pending 상태에 있게 된다.
func1(2, 3);
// 위의 코드를 읽는 순간, 즉, 함수를 실행하는 순간, a,b 값이 명확해짐과 동시에 조급한 실행법이 적용돼 함수의 몸통 부분인 `return a+b`를 실행하게 된다.
// 이에 따라 5라는 값을 리턴하게 된다(조급한 실행법으로).

익명함수를 이용한 컴파일러의 표현식 계산 과정 재검토

: 사실 앞서 말한 JS, TS의 함수 표현식은 다른 프로그래밍 언어에서 익명 함수로 알려진 것의 다른 표현이다.

const func1 = (function (a,b) { return a+b })(2,3)
// 이렇게 했을 때 실행 순서가 어떻게 될까?
// 1. const func1 = 이부분을 읽으면서 func1에 뭔가를 할당할거구나 하면서 오른쪽 초기화부분을 봅니다.
// 2. (function (a,b) { return a+b }) 를 해석하면서 느긋한 계산법으로 일단 a,b 를 모르므로 패스합니다.
// 3. (2,3) 실제 함수를 실행하고, 2,3이라고 a,b 값을 명확히 해줬으므로 조급한 계산법을 통해 5라는 값을 내고, func1에 할당하여 초기화를 완료합니다.

문(statement)이란 뭔가

: 문(statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다. 이에 따라, 프로그램은 문의 집합으로 이뤄지며, 프로그래밍이란 문을 작성하고 순서에 맞게 나열하는 것이다. 문은 여러 토큰으로 구성되는데, 토큰이란 문법적인 의미를 가지며 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다. 예를 들어서,

var count = 10;

이 있을 때 이를 토큰 단위로 쪼개보면 아래와 같다
var, count, =, 10, ; : 토큰

문은 컴퓨터에 내리는 명령이므로 명령문이라고도 부른다. 이러한 문은 선언문, 할당문, 조건문, 반복문 등으로 구분할 수 있다.

실행식 문과 표현식 방식의 문

: 본래 ES5 까지는 실행식 문만 지원하던 JS는 ESNext로 오면서 이에 더해 타입스크립트는 표현식 방식의 문까지 같이 지원한다. 즉, 다중 패러다임 언어와 같아졌다. 예를 들어,

const func1 = function () { return 3 } // 실행식 문
// 위와 같이 중괄호로 감싼 부분에 복수 개의 코드가 들어간다면 '다중 실행문'이라고 할 수 있다.
const func1 = () => 3; // 표현식 방식의 문 
const func1 = ():number => 3; // 타입스크립트로 표현한 표현식 방식의 문 

이에 더하여, JS, TS에서는

if(x > y) {
	console.log('x가 y보다 크다');
    return true;
}

위와 같이 실행문 식 문과 표현식 방식의 문을 아까 말했듯이 이중 지원하기 때문에 같이 쓸 수 있다. 사실 이렇게 다중 지원 언어가 아니었다면 x > y 자체도 하나의 표현식이고 그에 따라 실행문 방식의 문만 지원했다면

if(return x > y)

처럼 이상한 형태가 됐을 수 있다. 역으로 표현식 방식만 제공했다면 return 키워드도 쓸 수 없었을 것이다.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글