본문 바로가기
👩‍💻 Programming/JavaScript

초심자를 위한 함수의 정의와 arguments_1. 객체로서의 함수 from Secrets of the JavaScript Ninja

by codingBear 2022. 4. 5.
728x90
반응형

이번 글은 'Secrets of the JavaScript Ninja'의 'Chapter 3. First-class functions for the novice: definitions and arguments'를 바탕으로 작성하였습니다.


핵심 Concepts

  • 함수를 이해하는 것이 중요한 이유
  • 함수는 어떻게 first-class objects일까?
  • 함수를 정의하는 방법들
  • 파라미터는 어떻게 부여되는가

사전 지식 체크!

  • callbak funtion은 어떤 환경에서 쓰이는가? 동기적인 환경? 아니면 비동기적인 환경?
  • arrow functionfunction expression의 차이점?
  • default parameter를 사용하는가?

들어가며

 JavaScript를 통달하기 위해서는 JavaScript가 functional language라는 사실을 깨달아야 한다. 가장 중요한 점은 JavaScript에서 function은 first-class objects 혹은 first-class citizens라는 점이다. 일반적인 JavaScript의 data type처럼 function은 variable로 참조되거나 literal로 선언되기도 하고 function의 parameter로 쓰일 수도 있다. 


함수들의 차이점에 대해서

 함수에 대해 살펴보기에 앞서 우선 JavaScript 객체의 기능들을 살펴보자.

 

  • 객체는 literal로써 생성 ( ex. {})
  • 객체는 variables, array entries, 혹은 다른 객체의 properties로 할당된다.

 

  • 객체는 함수의 argument로 입력된다.

 

  • 객체는 함수의 반환값으로도 쓰인다.

 

  • 객체는 동적으로 만들어지거나 할당되는 properties를 보유한다.


Functions as first-class objects

 JavaScript에서 함수는 객체가 가지는 기능을 모두 가지며, 다른 객체들과 마찬가지로 취급된다. JavaScript의 기능을 예제를 통해 살펴보자.

 

  • literal을 통해 생성

 

  • variables, array entries, 다른 객체의 properties로 할당

 

  • 다른 함수의 argument로 입력

 

  • 함수의 반환값

 

  • 동적으로 만들어지거나 할당되는 properties를 보유

 

 JavaScript에서 객체와 함수의 기능은 거의 같으나 함수는 호출 가능(invokable)하다는 점이 다르다. first-class object의 특징 중 하나는 함수에 argument로서 할당된다는 점이다. 이와 같은 기능을 통해 callback funtion을 활용할 수 있다.


Callback funtions

 JavaScript에서 이벤트 처리 단계의 브라우저 혹은 다른 코드에 의해 나중에 호출되는 함수를 설정할 때마다, callback을 마련한다. callback이란 말은 적절한 시점에 시행되는 함수를 다른 코드가 불러들인다(callback)는 뜻에서 유래한다.

 다른 함수를 parameter로 받으며 그 함수를 callback으로 삼는 예제 코드를 살펴보자.

 

 

 assert function은 주로 argument를 두 개 받는데, 첫 번째 argument에 boolean 형식의 조건문을 입력하여 false가 나올 시 두 번째 argument가 출력된다. 첫 번째 argument가 true라면 아무 것도 실행되지 않고 통과된다.

 위 예제 코드를 성공적으로 실행하고 나면 다음과 같은 결과값이 출력된다.

 

 

 위 그림을 보면 useless function은 getText function을 argument로 받아 결과값을 성공적을 반환했음을 알 수 있다. 이는 useless function 안에서 getText function은 callback parameter로서 참조된다는 것이다. 즉 getText function은 useless function의 argument로 입력되어 useless function에 의해 호출되는 callback function이다.

 

 

 앞서 말했듯 JavaScript에서는 function을 first-class object로 취급하는데 아래 예제 코드처럼 함수의 argument에 곧바로 function을 할당하는 식으로 작성해도 위에 살펴본 예제 코드와 똑같이 동작한다.

 

 

 JavaScript의 중요한 특징 중 하나는  전체 코드 아무 데나 function을 작성할 수 있다는 점이다. 이로써 function이 코드 내 여러 위치에서 참조되지 않을 때 불필요한 이름으로 global namespace를 오염시킬 가능성을 제거할 수 있다.

 위의 예제 코드에서는 하나의 코드로써 다른 코드를 callback 했으나 callback funtion은 브라우저에 의해서도 호출될 수 있다. 해당 예제 코드를 살펴보자.

 

 

 위의 예제 코드는 mousemove event가 발생할 때마다 callback function이 브라우저에 의해 호출되는 function이다.

Soring with a comparator

 순서가 뒤섞인 array를 오름차순 혹은 내림차순으로 정렬한다고 가정해보자. JavaScript에서는 이를 위해 자체적으로 sort method를 제공한다. 우리는 sort method에 어떤 순서로 정렬할지 정하는 comparison algorithm만 정의하면 된다. sort algorithm은 비교할 필요가 있을 때마다 comparison algorithm을 호출할 것이다. 

 callback function은 전달된 값의 순서를 반대로 해야 할 경우 양수를 반환하고 그렇지 않은 경우 음수를, 두 값이 같으면 0을 반환한다. 전달된 a와 b를 빼면서 배열을 정렬하기 위해 필요한 값을 반환한다.

 

 

 우리는 JavaScript 엔진에 두 값을 비교할 필요가 있을 때마다 callback funtion을 제공하는 것이다. 


Fun with functions as objects

 JavaScript에서 function의 놀라운 기능 중 하나는 function에 객체처럼 properties를 부여할 수 있다는 것이다.

 

 

 이를 활용해 아래 두 가지 방식으로 function을 활용 가능하다.

  • collection에 functions 저장하기: 관련된 function을 쉽게 관리 가능
  • Memoization: 이전에 계산된 값을 function에 저장함으로써 호출 시 성능 향상

Storing functions

 특정 이벤트 발생 시 호출되는 collections of callbacks를 관리하는 것과 같은 특정한 상황에서 function을 collection에 저장하면 향후 관리하기가 편하다. collection에 function을 저장할 때 어떤 function이 새로운 것이며 어느 것을 저장해야 하고, 이미 존재하는지 정하는 일이 난관이다. function의 유일성을 유지하지 않으면 하나의 이벤트가 발생할 때 여러 function이 실행되어 코드가 엉망이 될 것이다.

 이러한 중복 방지 작업 코드를 array와 for loop을 활용하여 작성할 수 있다.

 

 

 위 코드는 간단히 작성할 수 있지만 그만큼 성능은 떨어진다. 우선 store라는 이름의 객체를 생성한다. 이 객체는 두 가지 property를 가진다. 하나는 id값을 저장하며 다른 하나는 function을 저장하는 cache라는 이름의 객체이다. function은 add() method를 통해 cache에 저장된다.

 add() method에서는 우선 추가하려는 function이 store 객체 내에 이미 존재하는지 id로써 확인한다. 만일 존재하지 않는다면 id property에 nextId에서 1이 증가된 값을 부여하고 id값을 이름으로 삼아 cache의 property로 function을 추가한다. 성공적으로 function이 추가되었다면 true를 반환한다.


Self-memoizing functions

 memoization이란 이미 계산된 값을 저장 가능한 function을 만드는 과정이다. function이 값을 계산해낼 때마다 그 값을 function의 argument에 따라 저장한다. 이렇게 하면 같은 argument set이 호출될 때 새로 결과값을 계산하는 대신 미리 계산하여 저장해둔 결과값을 반환할 수 있다. memoization을 하면 복잡한 계산을 피하여 성능을 확연히 개선할 수 있다. memoization은 animations, 자주 바뀌지 않는 data 탐색, 시간을 많이 잡아먹는 계산에 특히 유용하다.

 아래 예제 코드는 간단한 memoization이다.

 

 

 위 예제 코드의 동작 순서는 다음과 같다.

  1. isPrime function에서 chache로 사용할 answers property가 이미 생성되었는지 확인하고 없다면 새로 생성
  2. 전달된 값에 대한 결과가 이미 answers에 저장되어 있는지 확인
  3. var prime과 for문을 거쳐 value가 소수라면 answers property에 저장

 이렇게 생성된 cache는 function의 property이기 때문에 function 자체가 살아 있는 한 function과 함께 존재한다.

 이 접근 방식은 장점이 두 가지이다.

  • 이미 계산된 값을 불러오기 용이하다.
  • function 자체로 위 과정이 수행되기에 다른 요청을 수행하거나 추가 작업을 할 필요가 없다.

허나 아래와 같은 단점 역시 존재한다.

  • 메모리를 희생해야 한다.
  • function이나 method는 하나의 작업만을 수행해야 하나 caching 작업이 섞여 있다.
  • 결과값이 기존 input값에 기초하기 때문에 load-test를 수행하거나 알고리즘의 성능을 측정하기 어렵다.

 함께 보기

  • sort() method

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

 

Array.prototype.sort() - JavaScript | MDN

The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

developer.mozilla.org

  • assert() method

https://developer.mozilla.org/en-US/docs/Web/API/console/assert

 

console.assert() - Web APIs | MDN

The console.assert() method writes an error message to the console if the assertion is false. If the assertion is true, nothing happens.

developer.mozilla.org

https://www.w3schools.com/nodejs/met_assert.asp

 

Node.js assert() Method

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

728x90
반응형

댓글