VUE3.0을 빠르게 시작하는 방법: 학습 입력
관련 권장 사항: JavaScript 학습 튜토리얼
함수형 프로그래밍에 대한 많은 설명을 보았지만 대부분은 이론적인 수준이고 일부는 순수 함수형 프로그래밍 언어에만 해당됩니다. 하스켈과 같은. 이 글의 목적은 내 눈으로 보기에 JavaScript에서의 함수형 프로그래밍의 구체적인 실천에 대해 이야기하는 것입니다. "내 눈으로 보기"라고 하는 이유는 내가 말하는 내용은 단지 내 개인적인 의견일 뿐이며 일부 엄격한 개념과 충돌할 수 있다는 의미입니다.
이 글에서는 형식적인 개념 소개를 많이 생략하고 JavaScript에서 함수형 코드가 무엇인지, 함수형 코드와 일반 작성의 차이점은 무엇인지, 함수형 코드가 우리에게 가져올 수 있는 이점은 무엇인지, 공통 함수형 모델은 무엇인지 보여주는 데 중점을 둘 것입니다.
함수형 프로그래밍은 함수를 주요 전달자로 사용하는 프로그래밍 방법으로 이해될 수 있다고 생각합니다. 함수를 사용하여 일반 표현식을 분해하고 추상화하는
것은 명령형과 비교되는 것입니다. 주요 요점은 다음과 같습니다:
더 명확한 의미, 더 높은 재사용성, 더 높은 유지 관리성, 더 나은 범위 제한 및 더 적은 부작용 기본 기능적 프로그래밍 다음 예는Javascript 코드
의 특정 기능적 표현입니다.
// 배열의 각 단어를 대문자로 표시합니다. 첫 글자 // 일반 쓰기 const arr = ['apple', 'pen', 'apple-pen'] for(const i in arr){ const c = arr[i][0]; arr[i] = c.toUpperCase() + arr[i].slice(1) } console.log(arr); // 함수형 작성 방법 - function upperFirst(word) { return word[0].toUpperCase() + word.slice(1) } 함수 wordToUpperCase(arr) { return arr.map(upperFirst) } console.log(wordToUpperCase(['apple', 'pen', 'apple-pen'])); // 기능적 작성 방법 2 console.log(arr.map(['apple', 'pen', 'apple-pen'], word => word[0].toUpperCase() + word.slice(1)))
상황이 더욱 복잡해지면 표현식을 작성하는 방식에 여러 가지 문제가 발생합니다.
의미
가 명확하지 않고 점차 유지 관리가 어려워지며 재사용성이 떨어지고 더 많은 코드가 생성되며 많은 중간 변수가 생성됩니다. 함수형 프로그래밍은 위의 문제를 잘 해결했습니다. 먼저 함수 캡슐화를 사용하여 함수를 분해하고(세분성은 고유하지 않음) 이를 다른 함수로 캡슐화한 다음 결합된 호출을 사용하여 목적을 달성하는 함수 작성 방법 1을 참조하세요. 이를 통해 표현이 명확해지고 유지 관리, 재사용 및 확장이 쉬워집니다. 둘째, 고차 함수를 사용하는 Array.map은 배열 탐색을 위해 for...of를 대체하여 중간 변수와 작업을 줄입니다.
기능적 작성 방법 1과 기능적 작성 방법 2의 주요 차이점은 나중에 함수를 재사용할 수 있는지 여부를 고려할 수 있다는 점입니다. 그렇지 않은 경우 후자가 더 좋습니다.
위의 함수형 작성 방법 2를 통해 함수형 코드를 작성하는 과정에서 수평 확장, 즉 여러 레이어의 중첩이 발생하기 쉽다는 것을 알 수 있습니다. 아래에서는 극단적인 예를 들어보겠습니다.
자바스크립트 코드
// 숫자의 합 계산 // 일반적인 작성 방법 console.log(1 + 2 + 3 - 4) // 함수형 쓰기 함수 sum(a, b) { a + b를 반환 } 함수 하위(a, b) { 반환 a - b } console.log(sub(sum(sum(1, 2), 3), 4); 이 예제는 수평 확장의 극단적인 경우만 보여줍니다. 함수의 중첩된 수준 수가 계속 증가함에 따라 코드 읽기가 어려워집니다. . 성능이 크게 저하되고 실수하기 쉽습니다. 이 경우 다음과 같은 체인 최적화와 같은 여러 가지 최적화 방법을 고려할 수 있습니다. // 쓰기 최적화(글쎄, 읽으셨군요. 이것은 lodash의 체인 쓰기입니다) Javascript 코드 const utils = { 체인(a) { this._temp = a; 이거 돌려줘; }, 합계(b) { this._temp += b; 이거 돌려줘; }, 하위(b) { this._temp -= b; 이거 돌려줘; }, 값() { const _temp = this._temp; this._temp = 정의되지 않음; _temp를 반환합니다; } }; console.log(utils.chain(1).sum(2).sum(3).sub(4).value());
이렇게 다시 작성하면 전체 구조가 더 명확해지고 체인의 각 링크가 더 명확해집니다. 해야 할 일도 쉽게 표시할 수 있습니다. 함수 중첩과 연결을 비교한 또 다른 좋은 예는 콜백 함수와 Promise 패턴입니다.
Javascript 코드
// 두 개의 인터페이스를 순차적으로 요청 // 콜백 함수 import $ from 'jquery', (rs) => { 만약(rs){ $.post('a/url/to/another/target', (rs2) => { 만약(rs2){ $.post('a/url/to/third/target'); } }); } }); // 'catta'에서 가져오기 요청을 약속합니다. // catta는 fetch, jsonp, ajax를 지원하고 종속성이 없는 경량 요청 도구입니다. request('a/url/to/target') .then(rs => rs ? $.post('a/url/to/another/target') : Promise.reject()) .then(rs2 => rs2 ? $.post('a/url/to/third/target') : Promise.reject());
콜백 함수 중첩 수준 및 단일 수준 복잡성이 증가함에 따라 부풀어 오르고 유지 관리가 어렵지만 Promise의 체인 구조는 복잡성이 높을 때 여전히 수직으로 확장될 수 있으며 계층적 격리가 매우 명확합니다.
일반적인 함수형 프로그래밍 모델인
는 해제되지 않은 코드 블록에 로컬 변수를 유지할 수 있는 것으로
클로저의 개념은 비교적 추상적이며 이 기능을 사용하는
이유는 무엇입니까? 가방이 우리를 데려올 수 있나요?
먼저 클로저를 생성하는 방법을 살펴보겠습니다:
Javascript 코드
// 클로저 함수 만들기 makeCounter() { k = 0이라고 하자; 반환 함수() { ++k를 반환합니다; } } const counter = makeCounter(); console.log(counter()); // 1 console.log(counter()); // 2
makeCounter 이 함수의 코드 블록은 반환된 함수에서 로컬 변수 k를 참조합니다. 함수가 실행되면 시스템에 의해 재활용되어 클로저가 생성됩니다. 이 클로저의 기능은 내부 함수가 호출될 때 변수를 재사용할 수 있도록 지역 변수를 "유지"하는 것입니다. 전역 변수와 달리 이 변수는 함수 내부에서만 참조할 수 있습니다.
즉, 클로저는 실제로 함수 전용인 "영구 변수"를 생성합니다.
따라서 이 예에서 클로저를 생성하기 위한 조건은
내부 함수와 외부 함수가 있다는 결론을 내릴 수 있습니다. 내부 함수는 외부 함수의 지역 변수를 참조합니다. 클로저의 주요 목적은 정의하는 것입니다. 일부 기능 도메인 제한 영구 변수, 이러한 변수는 캐싱 또는 중간 계산 등에 사용될 수 있습니다.
Javascript 코드
// 간단한 캐싱 도구 // 익명 함수가 클로저를 생성합니다. const 캐시 = (function() { const 저장소 = {}; 반품 { get(키) { 반품 매장[키]; }, 세트(키, 값) { 저장소[키] = 발; } } }()); 캐시.set('a', 1); 캐시.get('a'); // 1
위의 예는 저장소 객체를 항상 참조할 수 있도록 간단한 캐싱 도구를 구현한 것입니다. , 재활용되지 않습니다.
클로저의 단점: 영속 변수는 정상적으로 해제되지 않고 메모리 공간을 계속 차지하므로 메모리 낭비가 쉽게 발생할 수 있으므로 일반적으로 몇 가지 추가적인 수동 정리 메커니즘이 필요합니다.
함수를 받아들이거나 반환하는 함수를 고차 함수(higher-order function)라고 합니다.
아주 차가운 단어처럼 들리지만 사실 우리가 자주 사용하지만 그 이름을 알지 못할 뿐입니다. JavaScript 함수는 일급 시민이고 매개 변수와 다른 함수의 반환 값으로 모두 사용될 수 있기 때문에 JavaScript 언어는 기본적으로 고차 함수를 지원합니다.
Array.map, Array.reduce, Array.filter와 같은 JavaScript의 기본 고차 함수를 자주 볼 수 있습니다.
map을 예로 들어Mapping
사용하는 방법을 살펴보겠습니다.
즉, 세트의 각 항목은 동일한 변환을 거쳐 새로운 세트
맵을 생성합니다. 고차 함수로서 함수 매개변수를 매핑의 논리적
Javascript 코드
로 받아들입니다. 새로운 배열을 구성할 배열 // 일반적인 작성 방법 const arr = [1,2,3] const rs = [] for(const n of arr); rs.push(++n) } console.log(rs) // map은
배열을 순회하기 위해 for...of 루프를 사용하여 위의 일반적인 작성 방법을
다시 작성합니다.추가 작업, 원본 배열을 변경할 위험이 있지만
맵 함수는 필요한 작업을 캡슐화하므로 매핑 논리의 함수 구현에만 신경 쓰면 코드 양과 측면 위험이 줄어 듭니다. 효과.
함수의 일부 매개변수를 제공하고 다른 매개변수를 허용하는 새로운 함수를 생성합니다.
이 용어를 자주 듣지 못할 수도 있지만 undescore 또는 lodash를 사용해 본 사람은 누구나 이 용어를 본 적이 있을 것입니다.
마법의 _.partial 함수가 있습니다.Javascript 코드
입니다.
// 대상 파일의 상대 경로를 기본 경로로 가져옵니다. // 일반적인 작성 방법은 const BASE = '/path/to/base'; path.relative(BASE, '/some/path'); // _.parical 재작성 const BASE = '/path/to/base'; constrelativeFromBase = _.partial(path.relative, BASE); constrelativePath =relativeFromBase('/some/path');
_.partial을 통해 새로운 함수relativeFromBase를 얻습니다. 이 함수가 호출되면 path.relative를 호출하는 것과 동일하며 기본적으로 첫 번째 매개변수가 BASE에 전달됩니다. 전달된 후속 매개변수는 순서대로 추가됩니다.
이 경우 우리가 실제로 달성하고 싶은 것은 어떤 경로에 상대적인 경로가 아니라 매번 BASE에 상대적인 경로를 얻는 것입니다. 커링을 사용하면 함수의 일부 매개변수에만 관심을 가질 수 있어 함수의 목적을 더 명확하게 만들고 더 간단하게 호출할 수 있습니다.
여러 함수의 기능을 결합하여 새로운 함수를 생성하는 방식입니다.
작성 방법(현재는 흐름이라고 함)
Javascript 코드
// 배열의 각 단어를 대문자로 작성하고 Base64를 수행합니다. //일반적인 쓰기 방법(중 하나) const arr = ['pen', 'apple', 'applypen'] const rs = [] for(const w of arr); rs.push(btoa(w.toUpperCase())) } console.log(rs); // _.flow rewrite const arr = ['pen', 'apple', 'applypen']; const upperAndBase64 = _.partialRight(_.map, _.flow(_.upperCase, btoa)); console.log(upperAndBase64(arr));
_.flow는 대문자 변환 기능과 Base64 변환 기능을 병합하여 새로운 기능을 생성합니다. 매개변수 기능으로 사용하거나 후속 재사용이 편리합니다.
내 관점에서 볼 때 JavaScript 함수형 프로그래밍에 대한 나의 이해는 많은 전통적인 개념과 다를 수 있습니다. 나는 고차 함수가 함수형 프로그래밍으로 간주된다고 생각하지 않습니다. 일반적인 함수 결합 호출, 체인 구조 등과 같은 다른 것들도 함수를 주요로 사용하는 한 함수형 프로그래밍의 범주에 속한다고 생각합니다. 담체.
그리고 저는 함수형 프로그래밍이 필요하지도 않고 필수 규칙이나 요구 사항이 되어서도 안 된다고 생각합니다. 객체지향이나 다른 아이디어와 마찬가지로 이것도 방법 중 하나입니다. 대부분의 경우 개념에 국한되기보다는 여러 가지가 결합된 형태로 이루어져야 합니다.
관련 권장사항: JavaScript 튜토리얼
위는 JavaScript 함수형 프로그래밍에 대한 자세한 설명입니다. 자세한 내용은 PHP 중국어 웹사이트의 다른 관련 기사를 참조하세요.