JavaScript의 함수 조합 및 커링에 대한 자세한 설명(예제 포함)
이 글은 JavaScript 함수 조합과 커링에 대한 자세한 설명을 제공합니다(예제 포함). 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
우리 모두는 단일 책임 원칙, 사실 객체지향 SOLID의 S(SRP, 단일 책임 원칙)를 알고 있습니다. 함수형 프로그래밍에서 각 함수는 하나의 단위이며 한 가지 작업만 수행해야 합니다. 그러나 현실 세계는 항상 복잡하며, 현실 세계를 프로그래밍에 매핑할 때 단일 기능은 그다지 의미가 없습니다. 이때 함수 구성과 커링이 필요합니다.
체인콜
jQuery를 사용해보신 분들이라면 $('.post').eq(1) 처럼 체인콜이 무엇인지 아실 겁니다. attr('data-test', 'test')
. JavaScript의 일부 기본 문자열 및 배열 메서드를 사용하여 체인 호출을 작성할 수도 있습니다. $('.post').eq(1).attr('data-test', 'test')
.javascript原生的一些字符串和数组的方法也能写出链式调用的风格:
'Hello, world!'.split('').reverse().join('') // "!dlrow ,olleH"
首先链式调用是基于对象的,上面的一个一个方法split
, reverse
, join
如果脱离的前面的对象"Hello, world!"是玩不起来的。
而在函数式编程中方法是独立于数据的,我们可以把上面以函数式的方式在写一遍:
const split = (tag, xs) => xs.split(tag) const reverse = xs => xs.reverse() const join = (tag, xs) => xs.join(tag) join('',reverse(split('','Hello, world!'))) // "!dlrow ,olleH"
你肯定会说,你是在逗我。这比链式调用好在哪儿了?这里还是依赖于数据的啊,没有传递`'Hello, world!',你这一串一串的函数组合也转不起来啊。这里唯一的好处也就是那几个单独的方法可以复用了。莫慌,后面还有那么多内容我怎么也会给你优化(忽悠)好的。再进行改造前,我们先介绍两个概念,部分应用和柯里化。
部分应用
部分应用是一种处理函数参数的流程,他会接收部分参数,然后返回一个函数接收更少的参数。这个就是部分应用。我们用bind
来实现一把:
const addThreeArg = (x, y, z) => x + y + z; const addTwoArg = addThreeNumber.bind(null, 1) const addOneArg = addThreeNumber.bind(null, 1, 2) addTwoArg(2, 3) // 6 addOneArg(7) // 10
上面利用bind
生成了另外两个函数,分别接受剩下的参数,这就是部分应用。当然你也可以通过其他方式实现。
部分应用存在的问题
部分应用主要的问题在于,它返回的函数类型无法直接推断。正如前面所说,部分应用返回一个函数接收更少的参数,而没有规定返回的参数具体是多少个。这也就是一些隐式的东西,你需要去查看代码。才知道返回的函数接收多少个参数。
柯里化
柯里化定义:你可以调一个函数,但是不一次将所有参数传给它。这个函数会返回一个函数去接收下一个参数。
const add = x => y => x + y const plusOne = add(1) plusOne(10) // 11
柯里化的函数返回一个只接收一个参数的函数,返回的函数类型可以预测。
当然在实际开发中,有很多的函数都不是柯里化的,我们可以使用一些工具函数来转化:
const curry = (fn) => { // fn可以是任何参数的函数 const arity = fn.length; return function $curry(...args) { if (args.length <p>也可以用开源库Ramda里提供的curry方法。</p><h3 id="哦-柯里化-有什么用呢">哦,柯里化。有什么用呢?</h3><p>举个例子</p><pre class="brush:php;toolbar:false">const currySplit = curry((tag, xs) => xs.split(tag)) const split = (tag, xs) => xs.split(tag) // 我现在需要一个函数去split "," const splitComma = currySplit(',') //by curry const splitComma = string => split(',', string)
可以看到柯里化的函数生成新函数时,和数据完全没有关系。对比两个生成新函数的过程,没有柯里化的相对而言就有一点啰嗦了。
函数组合
先给代码:
const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
其实compose做的事情一共两件:
接收一组函数,返回一个函数,不立即执行函数
组合函数,将传递给他的函数从左到右组合。
可能有同学对上面的reduceRight不是很熟悉,我给个2元和3元的例子:
const compose = (f, g) => (...args) => f(g(...args)) const compose3 = (f, g, z) => (...args) => f(g(z(...args)))
函数调用是从左到右,数据流也是一样的从左到右。当然你可以定义从右到左的,不过从语义上来说就不那么表意了。
好,现在让我们来优化一下最开始的例子:
const split = curry((tag, xs) => xs.split(tag)) const reverse = xs => xs.reverse() const join = curry((tag, xs) => xs.join(tag)) const reverseWords = compose(join(''), reverse, split('')) reverseWords('Hello,world!');
是不是简洁易于理解多了。这里的reverseWords
也是我们之前讲过的Pointfree的代码风格。不依赖数据和外部状态,就是组合在一起的一个函数。
Pointfree我在上一篇介绍过JS函数式编程 - 概念,也阐述了其优缺点,有兴趣的小伙伴可以看看。
函数组合的结合律
先回顾一下小学知识加法结合律:a+(b+c)=(a+b)+c
compose(f, compose(g, h)) === compose(compose(f, g), h);
split
, reverse
, join
메서드를 사용할 수 없습니다. 일어나세요. 함수형 프로그래밍에서 메서드는 데이터와 독립적입니다. 위의 내용을 함수형 방식으로 작성할 수 있습니다. const split = curry((tag, xs) => xs.split(tag)) const reverse = xs => xs.reverse() const join = curry((tag, xs) => xs.join(tag)) const getReverseArray = compose(reverse, split('')) const reverseWords = compose(join(''), getReverseArray) reverseWords('Hello,world!');
부분 적용은 함수 매개변수를 처리한 다음 더 적은 매개변수를 받은 함수를 반환하는 프로세스입니다. 이것은 응용 프로그램의 일부입니다. 이를 구현하기 위해
bind
를 사용합니다: rrreee위에서는 bind
를 사용하여 나머지 매개변수를 각각 허용하는 두 개의 다른 함수를 생성합니다. 애플리케이션. 물론 다른 방법으로도 할 수 있습니다.
일부 애플리케이션의 문제
일부 애플리케이션의 주요 문제는 반환하는 함수 유형을 직접 유추할 수 없다는 것입니다. 앞에서 언급했듯이 일부 응용 프로그램은 반환되는 매개 변수 수를 지정하지 않고 더 적은 수의 매개 변수를 허용하는 함수를 반환합니다. 이는 암시적인 내용이므로 코드를 살펴봐야 합니다. 그래야만 반환된 함수가 받는 매개변수 수를 알 수 있습니다.
아, 카레. 무슨 소용이 있나요?
#🎜🎜#예를 들어#🎜🎜#rrreee#🎜🎜#커리 함수가 새로운 함수를 생성할 때 데이터와는 아무런 관련이 없음을 알 수 있습니다. 새로운 함수를 생성하는 두 가지 프로세스를 비교하면 카레가 없는 프로세스는 상대적으로 장황합니다. #🎜🎜##🎜🎜#함수 조합#🎜🎜##🎜🎜#먼저 코드를 제공합니다. #🎜🎜#rrreee#🎜🎜#사실 Compose는 총 두 가지 작업을 수행합니다. #🎜🎜#- #🎜🎜#함수 세트를 수신하고, 함수를 반환하고, 함수를 즉시 실행하지 않습니다. #🎜🎜#
- #🎜🎜#함수 결합, 그리고 그에게 전달된 함수를 왼쪽에서 오른쪽으로 전달합니다. #🎜🎜#
reverseWords
는 이전에 이야기한 Pointfree 코드 스타일이기도 합니다. 데이터나 외부 상태에 의존하지 않고 함께 결합된 기능입니다. #🎜🎜##🎜🎜#Pointfree 이전 글에서 JS 함수형 프로그래밍의 개념을 소개했고, 장점과 단점도 설명했습니다. #🎜🎜#함수 조합의 결합 법칙
#🎜🎜# 먼저 초등학교 지식 덧셈의 결합 법칙을 살펴보겠습니다.a+(b+c)=(a+b)+c . 설명하지 않겠습니다. 여러분은 이해할 수 있을 것입니다. #🎜🎜##🎜🎜#돌이켜보면 함수 조합에는 실제로 결합 법칙이 있습니다. #🎜🎜#rrreee#🎜🎜#이것은 우리 프로그래밍에 있어서 마음대로 결합하고 캐시할 수 있다는 이점입니다. #🎜🎜 # rrreee#🎜🎜#뇌 지도 보충 자료: #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#
위 내용은 JavaScript의 함수 조합 및 커링에 대한 자세한 설명(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

C++ 람다 식은 다음을 포함하여 함수형 프로그래밍에 이점을 제공합니다. 단순성: 익명 인라인 함수는 코드 가독성을 향상시킵니다. 코드 재사용: 코드 재사용을 용이하게 하기 위해 람다 표현식을 전달하거나 저장할 수 있습니다. 캡슐화: 별도의 함수를 만들지 않고도 코드 조각을 캡슐화하는 방법을 제공합니다. 실제 사례: 목록에서 홀수를 필터링합니다. 목록의 요소 합계를 계산합니다. 람다 표현식은 함수형 프로그래밍의 단순성, 재사용성 및 캡슐화를 달성합니다.

게으른 평가는 게으른 데이터 구조를 사용하여 Go에서 구현할 수 있습니다. 즉, 실제 값을 캡슐화하고 필요할 때만 평가하는 래퍼 유형을 생성합니다. 실제로 필요할 때까지 중간 값 계산을 연기하여 기능적 프로그램에서 피보나치 수열 계산을 최적화합니다. 이는 불필요한 오버헤드를 제거하고 기능적 프로그램의 성능을 향상시킬 수 있습니다.

Go에서 함수형 프로그래밍을 사용할 때 주의해야 할 5가지 일반적인 실수와 함정이 있습니다. 실수로 참조를 수정하지 말고 새로 생성된 변수가 반환되는지 확인하세요. 동시성 문제를 해결하려면 동기화 메커니즘을 사용하거나 외부 변경 가능 상태 캡처를 피하세요. 코드 가독성과 유지 관리성을 향상하려면 부분 기능화를 아껴서 사용하세요. 애플리케이션의 견고성을 보장하기 위해 항상 함수의 오류를 처리하십시오. 인라인 함수, 평면화된 데이터 구조 및 작업 일괄 처리를 사용하여 성능에 미치는 영향을 고려하고 코드를 최적화하세요.

JS-Torch 소개 JS-Torch는 구문이 PyTorch와 매우 유사한 딥 러닝 JavaScript 라이브러리입니다. 여기에는 완전한 기능을 갖춘 텐서 객체(추적된 그라디언트와 함께 사용 가능), 딥 러닝 레이어 및 기능, 자동 미분 엔진이 포함되어 있습니다. JS-Torch는 JavaScript의 딥러닝 연구에 적합하며 딥러닝 개발을 가속화할 수 있는 다양한 편리한 도구와 기능을 제공합니다. Image PyTorch는 Meta 연구팀이 개발하고 유지 관리하는 오픈 소스 딥 러닝 프레임워크입니다. 신경망 모델을 구축하고 훈련하기 위한 풍부한 도구와 라이브러리 세트를 제공합니다. PyTorch는 간단하고 유연하며 사용하기 쉽게 설계되었으며 동적 계산 그래프 기능을 통해

pythonLambda 표현식은 간결하고 읽기 쉽고 사용하기 쉬운 코드를 생성하기 위한 강력하고 유연한 도구입니다. 다른 함수에 인수로 전달되거나 변수에 저장될 수 있는 익명 함수를 빠르게 생성하는 데 유용합니다. Lambda 표현식의 기본 구문은 다음과 같습니다.lambdaarguments:expression예를 들어 다음 Lambda 표현식은 두 개의 숫자를 추가합니다.lambdax,y:x+y 이 Lambda 표현식은 다음과 같이 다른 함수에 인수로 전달될 수 있습니다. defsum( x ,y):returnx+yresult=sum(lambdax,y:x+y,1,2)이 예에서는

Python의 람다 표현식은 익명 함수의 또 다른 구문 형태입니다. 프로그램 어디에서나 정의할 수 있는 작은 익명 함수입니다. 람다 식은 매개변수 목록과 유효한 Python 식일 수 있는 식으로 구성됩니다. Lambda 표현식의 구문은 다음과 같습니다:lambdaargument_list:expression.예를 들어 다음 Lambda 표현식은 두 숫자의 합계를 반환합니다:lambdax,y:x+y 이 Lambda 표현식은 맵과 같은 다른 함수에 전달될 수 있습니다. () 함수: 숫자=[ 1,2,3,4,5]결과=맵(람다

Go와 Node.js는 입력(강함/약함), 동시성(고루틴/이벤트 루프), 가비지 수집(자동/수동)에서 차이가 있습니다. Go는 높은 처리량과 낮은 대기 시간을 가지며 고부하 백엔드에 적합합니다. Node.js는 비동기 I/O에 적합하고 높은 동시성 및 짧은 요청에 적합합니다. 두 가지의 실제 사례에는 Kubernetes(Go), 데이터베이스 연결(Node.js) 및 웹 애플리케이션(Go/Node.js)이 포함됩니다. 최종 선택은 애플리케이션 요구 사항, 팀 기술 및 개인 선호도에 따라 달라집니다.
