JavaScript 인터뷰 마스터하기 : 함수 구성이란?

Google 데이터 센터 파이프 — Jorge Jorquera — (CC-BY-NC-ND-2.0)
“Master the JavaScript Interview”는 중급에서 상급 JavaScript 위치에 지원할 때 발생할 수있는 일반적인 질문에 대한 응시자를 준비하기 위해 설계된 일련의 게시물입니다. 실제 인터뷰에서 자주 사용하는 질문입니다.

함수형 프로그래밍은 JavaScript 세계를 이어받습니다. 몇 년 전만해도 함수형 프로그래밍이 무엇인지 아는 JavaScript 프로그래머는 거의 없었지만 지난 3 년 동안 내가 본 모든 대규모 응용 프로그램 코드베이스는 함수형 프로그래밍 아이디어를 많이 사용합니다.

함수 구성은 두 개 이상의 함수를 결합하여 새로운 함수를 생성하는 프로세스입니다. 함수를 구성하는 것은 데이터가 흐르도록 일련의 파이프를 함께 스냅하는 것과 같습니다.

간단히 말해서, 함수 'f'와`g '의 구성은`f (g (x))`로 정의 될 수 있는데, 이는 내부에서 오른쪽에서 왼쪽으로 평가됩니다. 다시 말해 평가 순서는 다음과 같습니다.

  1. `x`
  2. `g`
  3. `f`

코드를 자세히 살펴 보겠습니다. 각 사용자에게 프로필 페이지를 제공하기 위해 사용자의 전체 이름을 URL 슬러그로 변환한다고 가정합니다. 그러기 위해서는 일련의 단계를 거쳐야합니다.

  1. 공백으로 이름을 배열로 나누기
  2. 이름을 소문자로 매핑
  3. 대시와 결합
  4. URI 컴포넌트 인코딩

간단한 구현은 다음과 같습니다.

나쁘지 않다. 그러나 내가 당신에게 그것을 더 잘 읽을 수 있다고 말하면 어떨까요?

이러한 각 작업에 해당하는 작성 가능한 기능이 있다고 상상해보십시오. 이것은 다음과 같이 쓸 수 있습니다.

이것은 우리의 첫 번째 시도보다 읽기가 더 어려워 보이지만 거기에 매달립니다.

이를 위해 우리는`split ()`,`join ()`및`map ()`과 같은 컴포저 블 형태의 공통 유틸리티를 사용하고 있습니다. 구현은 다음과 같습니다.

toLowerCase ()를 제외하고 Lodash / fp에서 이러한 모든 기능의 프로덕션 테스트 버전을 사용할 수 있습니다. 다음과 같이 가져올 수 있습니다.

'lodash / fp'에서 {커리, 맵, 조인, 분할} 가져 오기;

또는 이렇게 :

const curry = require ( 'lodash / fp / curry');
const map = require ( 'lodash / fp / map');
// ...

나는 조금 게으르다. 이 카레는 기술적으로 실제 카레가 아니며 항상 단항 함수를 생성합니다. 대신 간단한 부분 적용입니다. “카레와 부분 응용의 차이점은 무엇입니까?”를 참조하십시오. 그러나이 데모의 목적 상 실제 카레 기능과 상호 교환 적으로 작동합니다.

우리의`toSlug ()`구현으로 돌아가서, 정말로 나를 괴롭히는 것이 있습니다.

그것은 나에게 많은 둥지처럼 보였고 읽기가 약간 혼란 스럽습니다. 우리는 이러한 함수를 자동으로 구성하는 함수로 중첩을 평평하게 만들 수 있습니다. 즉, 하나의 함수에서 출력을 가져 와서 최종 값을 추출 할 때까지 다음 함수의 입력에 자동으로 패치합니다.

생각해 보면, 배열 엑스트라 유틸리티는 이와 비슷한 기능을합니다. 값 목록을 가져 와서 각 값에 함수를 적용하여 단일 결과를 누적합니다. 값 자체는 함수일 수 있습니다. 이 함수를`reduce ()`라고하지만 위의 작성 동작을 일치 ​​시키려면 왼쪽에서 오른쪽 대신 오른쪽에서 왼쪽으로 줄여야합니다.

우리가 찾고있는 것을 정확하게하는`reduceRight ()`가 있습니다.

`.reduce ()`와 마찬가지로 배열`.reduceRight ()`메소드는 감속기 함수와 초기 값 (`x`)을 취합니다. 배열 함수 (오른쪽에서 왼쪽으로)를 반복하여 각각 누적 된 값 (`v`)에 적용합니다.

compose를 사용하면 중첩없이 위의 컴포지션을 다시 작성할 수 있습니다.

물론,`compose ()`는 lodash / fp와 함께 제공됩니다 :

'lodash / fp'에서 import {compose};

또는:

const compose = require ( 'lodash / fp / compose');

작곡은 수학적인 형태의 구성, 내부에서 생각할 때 훌륭하지만… 왼쪽에서 오른쪽으로 순서를 생각하고 싶다면 어떻게해야합니까?

일반적으로`pipe ()`라고하는 다른 형식이 있습니다. Lodash는`flow ()`라고 부릅니다.

구현은`.reduceRight ()`대신`.reduce ()`를 사용한다는 점을 제외하면`compose ()`와 정확히 동일합니다.

`pipe ()`로 구현 된`toSlug ()`함수를 보자 :

나에게 이것은 읽기 훨씬 쉽다.

하드 코어 기능 프로그래머는 기능 구성 측면에서 전체 애플리케이션을 정의합니다. 임시 변수가 필요하지 않도록 자주 사용합니다. `toSlug ()`의`pipe ()`버전을주의 깊게 살펴보면 특별한 점이있을 수 있습니다.

명령형 프로그래밍에서 일부 변수에 대해 변환을 수행 할 때 변환의 각 단계에서 변수에 대한 참조를 찾을 수 있습니다. 위의`pipe ()`구현은 포인트 프리 스타일로 작성되었으므로 작동하는 인수를 식별하지 않습니다.

단위 테스트 및 Redux 상태 감속기와 같은 파이프를 자주 사용하여 한 작업과 다음 작업 사이에 일시적인 값을 유지하기 위해 존재하는 중간 변수가 필요하지 않습니다.

처음에는 이상하게 들릴지 모르지만 실습을 통해 함수형 프로그래밍에서는 사물의 이름이 중요하지 않은 매우 추상적이고 일반화 된 함수로 작업하고 있음을 알 수 있습니다. 이름은 방해가됩니다. 변수를 불필요한 상용구로 생각하기 시작할 수 있습니다.

즉, 포인트 프리 스타일을 너무 멀리 가져갈 수 있다고 생각합니다. 너무 조밀하고 이해하기가 어려울 수 있지만 혼란 스러우면 여기 몇 가지 팁이 있습니다 ... 흐름을 활용하여 진행 상황을 추적 할 수 있습니다.

사용 방법은 다음과 같습니다.

`trace ()`는 좀 더 일반적인`tap ()`의 특수한 형식으로 파이프를 통해 흐르는 각 값에 대해 어떤 동작을 수행 할 수 있습니다. 알 겠어요? 파이프? 꼭지? 다음과 같이`tap ()`을 쓸 수 있습니다 :

이제`trace ()`가 특수한`tap ()`인 방법을 알 수 있습니다.

함수형 프로그래밍이 어떤지, 부분 응용 프로그램 및 커리가 함수 구성과 어떻게 협력하여 상용구가 적 으면서 더 읽기 쉬운 프로그램을 작성하는 데 도움이되는지 시작해야합니다.

시리즈 둘러보기

  • 폐쇄 란 무엇입니까?
  • 계급과 프로토 타입 상속의 차이점은 무엇입니까?
  • 순수한 기능이란 무엇입니까?
  • 기능 구성이란 무엇입니까?
  • 기능적 프로그래밍이란 무엇입니까?
  • 약속이란 무엇입니까?
  • 소프트 스킬

기술 레벨 업

Eric Elliott와 함께 JavaScript를 배우십시오. 회원이 아닌 경우 누락 된 것입니다.

Eric Elliott는“JavaScript 애플리케이션 프로그래밍”(O'Reilly)의 저자이자 고급 JavaScript 및 개발자 리더십 커리큘럼입니다. 그는 Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC 및 Usher, Frank Ocean, Metallica 등을 포함한 최고의 레코딩 아티스트를위한 소프트웨어 경험에 기여했습니다.

그는 세계에서 가장 아름다운 여성과 함께 원하는 곳 어디에서나 일합니다.