JS Reboot - 공리와 함수

cos·2020년 9월 6일
0

JS Reboot

목록 보기
1/2
post-thumbnail

최근 글쓴이는 우아한테크러닝 3기 교육을 받고있습니다. 이전에 사용했던 Javascript 스펙들을 다시보게 되면서 배운 점들을 시리즈 글로 올려볼까 합니다.

공리

갑자기 JS에서 뜬금없이 공리라는 단어 이야기가 나오냐고 생각하겠지만, 이야기를 들어보면 프로그래밍 언어들을 이해하는데 정말 큰 도움이 될것입니다. 공리라는 단어를 들어보신 적 있으신가요? 위키백과를 찾아보면 공리란 논리학이나 수학 등의 이론체계에서 가장 기초적인 근거가 되는 명제라고 정의되어 있습니다.

글로만 보면 이해되기 어려울 수 있는데, 몇가지 예시를 볼까요?

  • a=ba = b 라면 a+c=b+ca + c = b + c이다.
  • 집합 중 아무런 원소도 없는 공집합이 존재한다.
  • 자연수 aa가 존재한다면 그 다음 (1만큼 큰) 자연수 a+1a + 1이 존재한다.

위 문장들을 증명할 수 있을까요? 생각만 해도 머리가 지끈지끈하죠... 사실 불가능합니다. 공리는 마치 건물을 건설할 때 기반이 되는 철근을 심는 것 처럼 한 이론 안에서 가장 기반이 되는 요소들입니다. 또한, 위 예시들을 통해 수학의 여러 명제들이 증명되듯 여러 공리를 모아 이론들을 발전시킵니다.

Javascript에서 공리

그렇다면, Javascript에서 공리는 어떤 것이 있을까요? 교육 중 가장 인상깊었던 문구중 하나는 바로 변수에는 값이 들어가야된다 라는 공리였습니다. 진짜 별거 아닌 한 문장은 이후 뒤로 갈수록 더욱 잘 사용됩니다. 위에서 언급했듯, 이 공리를 통해 Javascript의 스펙을 점차 계속 쌓아갈 수 있다는 것입니다.

다른 말로는 앞으로 어려운 개념, 스펙을 다루게 될 때 까고 까고 안에 들어가다보면, 그 안에 정해놓은 공리로 이루어져 있기 때문에 기반을 잘 이해하면 이를 잘 이용해 어려운 개념도 잘 이해할 수 있을것입니다.

함수

함수는 거의 모든 언어에 있는 문법중 하나입니다. 간단한 형식부터 알아볼까요?

function foo() {
  // do something
}

다음과 같이 foo라는 함수를 만들었습니다. 여기에 한가지 공리를 더한다면, 함수는 값으로 취급한다라는 것입니다. 그렇다면, 첫 공리와 합쳐 다음과 같이 foo함수를 변수에 저장할 수 있습니다.

const bar = foo; // Possible
bar(); // Possible

함수선언식과 함수표현식

함수는 다음과 같이 두가지 방식으로 정의할 수 있습니다.

function foo() {
  console.log("함수선언식");
}

const bar = fucntion fun() {
  console.log("함수표현식");
};

foo(); // Possible
bar(); // Possible
fun(); // ERROR
  • 함수표현식은 변수이기 때문에, 세미콜론을 붙어줘야 합니다. 반대로 선언식은 선언만 하는 식이기 때문에 세미콜론을 붙이지 않아도 됩니다.
  • 함수표현식에서 사용한 이름 fun은 사용할 수 없는 이름입니다. 사용할 수 없는 이름이기 때문에 다음과 같이 이름을 생략해 많이 사용합니다. 당연히 함수선언식을 통해서는 이름을 생략할 수 없습니다.
const bar = fucntion () {
  console.log("함수표현식");
};

function () { // ERROR
  console.log("함수선언식?"); 
}

이 때 함수는 값이기 때문에 마치 값처럼 사용하려면, 괄호를 사용하면 에러없이 사용할 수 있습니다. 다만, JS에서 값을 그냥 쓰게 된다면 아무런 효과가 없는 것 처럼, 괄호를 사용해 함수를 쓴다면 선언만 하고 사용되지 않고 프로그램이 끝나버립니다. 이 함수를 사용하고 싶다면, 함수를 실행할 때 함수이름에 괄호를 넣는 것 처럼 괄호를 하나 더 넣으면 됩니다. 다만 이렇게 함수를 사용한다면 이 함수는 단 한번만 사용되는 함수로 사용되는데 이를 IIFE (Immediately Invoked Function Expressions), 즉시 호출 함수 표현식이라고 합니다.

(function() { // 함수를 값으로 쓸려면 괄호를 사용함. Possible

}) // 다만 호출되지 않음

(function() {

})() // 이 줄을 지나갈 때 딱 한번만 실행되는 함수! 즉시실행함수

콜백함수와 일급함수

함수에는 매개변수와 반환값이 있죠. 결국 그 두가지도 값이고, 함수도 값이기 때문에 매개변수와 반환값에도 함수를 넣을 수 있습니다.

function foo(x) {
  x();
  return function() {
    console.log("second");
  }
}

const y = foo(function() {
  console.log("first");
});

y(); // first -> second

foo함수는 두가지 특징을 가지고 있습니다.

  • y 변수는 foo함수를 호출해 값을 할당받는데, 매개변수로 first를 출력하는 함수를 넣어 호출합니다. 이와 같이 매개변수로 함수를 받는 함수를 콜백함수라고 합니다.
  • y 변수를 선언할 때 foo함수에서 second를 출력하는 함수를 리턴받습니다. 이와 같이 함수를 리턴하는 함수를 일급함수라고 합니다.

💡 React에서 HOC(High Order Component)도 함수 매개변수로 컴포넌트를 받아 컴포넌트를 리턴하는데, 이는 일급함수(High Order Function)에서 온 개념입니다.

동적바인딩과 클래스

Javascript 함수는 모두 리턴값을 가집니다. 만약 함수 안에 return문이 없다면 undefined가 리턴됩니다. 다만, 함수 호출 앞에 new를 붙이게 된다면 리턴되는 값은 달라집니다. 바로 빈 오브젝트 {}를 리턴합니다.

function foo() {
  this.fds = 10; // 동적바인딩
}

const y = new foo(); // 생성자가 작동됨

console.log(y); // { fds: 10 }

if (y instanceof foo) { // y 가 foo 함수로 만든 객체인가?

}

위 예시에서 foo 함수 안 this는 무슨 역활을 할까요? 바로 new를 통해 생성된 빈 오브젝트를 가리키는 this입니다. Javascript에서 this는 정말 많이 사용하기 때문에 쓸 때 마다 햇갈리기 마련인데, 위 예시에서는 빈 오브젝트에 값을 넣은 것입니다. 그럼 이러한 의문점이 생길 것인데, new를 붙여야지만 오브젝트가 만들어지는데 어떻게 그 오브젝트를 찾아서 값을 넣을까요? 바로 Javascript의 스펙중 동적바인딩을 통해 값을 찾게 됩니다. this를 현재 컨텍스트에서 어떻것을 사용해야 될지 찾게 되고, new를 사용하기 때문에 오브젝트에 주입하게 되는것입니다.

이렇게 new 키워드를 사용해 함수로 객체를 만들면 어떤 장점이 있을까요? 가장 큰 이유로는 객체의 유형, 형태를 추측할 수 있기 때문입니다. Javascript의 장점이자 단점인 동적 타입 때문에, 객체 안에는 직접 확인하기 전까지는 객체가 어떻게 구성되어 있는지 확인하기 어렵습니다. 그러나 함수를 통해 객체를 만들게된다면, 이 함수의 구성을 토대로 생성되는 변수들은 모두 이 함수의 구성을 따르기 때문에 객체의 형태를 확인할 수 있습니다! 특히 스펙 중 instanceof 구문을 사용하면 쉽게 이 변수가 특정 함수를 통해 만들어졌는지 확인 가능합니다.

다만, 함수의 원래 목적에는 맞지 않기 때문에, ES6부터 추가된 class 구문을 사용하면 더욱 의미있게 사용할 수 있습니다.

function foo() {
  this.name = 10;
}

class bar {
  constructor() {
    this.name = 10;
  }
}

const z = new bar();

foo(); // 호출 가능한데 만드는 의미에 맞지 않는다.
bar(); // Error!

정리하자면, Javascript의 class는 결국 함수로 이루어져있는 스펙입니다. 되도록이면 함수보다 class를 사용하는 것이 권장됩니다. 위와 같이 foo 함수와 bar 클래스가 만들어져있을때 하단 두 줄을 보면 foo를 사용할 때엔 에러가 뜨지 않아 어떤 점에 문제가 생겼는지 확인하기 어려운데, bar를 사용할 때엔 에러가 바로 떠 사용에 문제가 있단 것을 확인할 수 있습니다.

다음에는 실행 컨텍스트와 클로저에 대해 다뤄보겠습니다.

참고문서

profile
잡다한거 하는 개발자

0개의 댓글