函數(shù)式編程術(shù)語(yǔ)解析
Arity
指函數(shù)的參數(shù)數(shù)量,由 -ary 和 -ity 這兩個(gè)英文后綴拼接而成:
- const sum = (a, b) => a + b;
 - const Arity = sum.length;
 - console.log(Arity);
 - // 輸出結(jié)果為 2
 
Higher-Order Functions
高階函數(shù),此類函數(shù)可以接收其他函數(shù)作為參數(shù),也可以返回一個(gè)函數(shù)作為返回值:
- const filter = (predFunc, list) => {
 - const results = [];
 - list.forEach((listItem) => {
 - if (predFunc(listItem)) {
 - results.push(listItem);
 - }
 - });
 - return results;
 - }
 - // filter 這個(gè)函數(shù)就是將一個(gè)函數(shù)作為參數(shù)傳入
 - // 但這都么有什么,主要是后面is函數(shù)返回一個(gè)函數(shù)
 - const is = (type) => (x) => Object(x) instanceof type;
 - // is這個(gè)函數(shù)就是將一個(gè)函數(shù)作為返回值返回到下面的調(diào)用之中
 - filter(is(Number), [0, '1', 2, null]);
 - // 上面函數(shù)調(diào)用的結(jié)果是 [0, 2]
 
Partial Application
偏函數(shù),在原函數(shù)的基礎(chǔ)上預(yù)填充(pre-filling)部分參數(shù)并返回的新函數(shù):
- // 下面是一個(gè)創(chuàng)建偏函數(shù)的輔助函數(shù),下面函數(shù)將一個(gè)函數(shù)和這個(gè)函數(shù)所需要
 - // 的除了***一個(gè)參數(shù)的參數(shù)傳入,返回一個(gè)新的函數(shù),這個(gè)新的函數(shù)的參數(shù)為原
 - // 函數(shù)的***一個(gè)參數(shù)
 - const partial = (func, ...args) => (...moreArgs) => func(...args, ...moreArgs);
 - // 寫一個(gè)將三個(gè)數(shù)字相加的函數(shù)
 - const add3 = (a, b, c) => a + b + c;
 - // 預(yù)填充 (add3, 2, 3) 三個(gè)參數(shù),空置***一個(gè)參數(shù),返回一個(gè)新的函數(shù),重點(diǎn)是返回一個(gè)新的函數(shù)
 - const fivePlus = partial(add3, 2, 3); // (c) => 2 + 3 + c
 - fivePlus(4);
 - // => 9
 
Currying
柯里化,將一個(gè)接收多個(gè)參數(shù)的函數(shù)轉(zhuǎn)化為單參數(shù)函數(shù)的方式,轉(zhuǎn)化后的函數(shù)每次只接收一個(gè)參數(shù),然后返回一個(gè)新函數(shù),新函數(shù)可以繼續(xù)接收參數(shù),直到接收到所有的參數(shù):
- const sum = (a, b) => a + b;
 - sum(2, 3);
 - // => 6
 - const curriedSum = (a) => (b) => a + b;
 - curriedSum(40)(2);
 - // => 42.
 - const add2 = curriedSum(2);
 - // (b) => 2 + b
 - add2(10);
 - // => 12
 
Function Composition
函數(shù)合成,接收多個(gè)函數(shù)作為參數(shù)并返回一個(gè)新函數(shù)的方式,新函數(shù)按照傳入的參數(shù)順序,從右往左依次執(zhí)行,前一個(gè)函數(shù)的返回值是后一個(gè)函數(shù)的輸入值:
- const compose = (f, g) => (a) => f(g(a));
 - const floorAndToString = compose((val) => val.toString(), Math.floor);
 - floorAndToString(121.212121);
 - // => "121"
 
Purity
一個(gè)純函數(shù)需要滿足兩個(gè)條件,***是函數(shù)的返回值只能由輸入值(函數(shù)接收的參數(shù))決定,也就是說(shuō)純函數(shù)接收相同的參數(shù)會(huì)返回相同的值;第二是純函數(shù)不會(huì)對(duì)自身作用域之外的運(yùn)環(huán)境產(chǎn)生副作用(side effects),比如說(shuō)不會(huì)改變外部環(huán)境中變量的值,這會(huì)被認(rèn)為是不安全的行為:純函數(shù)示例:
- const greet = (name) => "Hi, " + name ;
 - greet("Brianne")
 - // => "Hi, Brianne"
 
Side effects
如果函數(shù)或表達(dá)式與其自身作用域之外的可變數(shù)據(jù)(mutable data)發(fā)生了讀寫操作,那么此時(shí)函數(shù)和表達(dá)式就產(chǎn)生了副作用:
- let greeting;
 - const greet = () => greeting = "Hi, " + window.name;
 - // greet() 執(zhí)行時(shí)更改了外部環(huán)境的變量
 - greet();
 - // => "Hi, Brianne"
 - // new Date() 是可變數(shù)據(jù)
 - const differentEveryTime = new Date();
 
Point-Free Style
point-free style 是一種不顯式向函數(shù)傳遞參數(shù)的代碼風(fēng)格,通常需要柯里化和高階函數(shù)來(lái)實(shí)現(xiàn):
- const map = (fn) => (list) => list.map(fn);
 - const add = (a) => (b) => a + b;
 - // Not points-free
 - // numbers 是一個(gè)顯式傳遞的參數(shù)
 - const incrementAll = (numbers) => map(add(1))(numbers);
 - // Points-free
 - // add(1) 的返回值隱式傳遞給了 map,作為 map 的 list 參數(shù)
 - const incrementAll2 = map(add(1));
 
Predicate
斷言,一個(gè)返回布爾值的函數(shù):
- const predicate = (a) => a > 2;
 - [1, 2, 3, 4].filter(predicate);
 - // => [3, 4]
 
Constant
常量,初始化后不能再次執(zhí)行賦值操作的數(shù)據(jù)類型:
- const five = 5;
 - const john = { name: 'John', age: 30 };
 - // 因?yàn)槌A坎豢勺儯韵旅姹磉_(dá)式一定為 true
 - john.age + five === ({ name: 'John', age: 30 }).age + (5);
 
常量具有 referentially transparent 的特性,也就是說(shuō)將程序中出現(xiàn)的常量替換為它們實(shí)際的值,并不會(huì)影響程序的結(jié)果。譯者話外:實(shí)際上在 JavaScript 中的 const 所聲明的常量并不是完全穩(wěn)定的,使用 Immutable.js 演示更加恰當(dāng):
- // 這里的fromJS(), get()函數(shù)都是immutable.js所提供的方法
 - const five = fromJS(5);
 - const john = fromJS({name: 'John', age: 30});
 - john.get('age') + five === ({ name: 'John', age: 30 }).age + (5);
 
Functor
functor 都擁有 map 函數(shù),并且在執(zhí)行 map 之后會(huì)返回一個(gè)新的 functor:
- object.map(x => x) === object;
 - object.map(x => f(g(x))) === object.map(g).map(f);
 
JavaScript 中最常見(jiàn)的 functor 就是數(shù)組類型的實(shí)例:
- [1, 2, 3].map(x => x);
 - // => [1, 2, 3]
 - const f = x => x + 1;
 - const g = x => x * 2;
 - [1, 2, 3].map(x => f(g(x)));
 - // => [3, 5, 7]
 - [1, 2, 3].map(g).map(f);
 - // => [3, 5, 7]
 
Lift
lift 發(fā)生在你將值放入 functor 的時(shí)候,如果你將函數(shù) lift 進(jìn)了 Applicative Functor,那么就可以使用這個(gè)函數(shù)處理傳遞給這個(gè) functor 的值。某些 lift 的實(shí)現(xiàn)擁有 lift 或 liftA2 函數(shù),便于在 functor 上執(zhí)行相關(guān)的函數(shù):
- const mult = (a, b) => a * b;
 - const liftedMult = lift(mult);
 - // => this function now works on functors like array
 - liftedMult([1, 2], [3]);
 - // => [3, 6]
 - lift((a, b) => a + b)([1, 2], [3, 4]);
 - // => [4, 5, 5, 6]
 
lift 一個(gè)單參數(shù)的函數(shù)非常類似于 map 操作:
- const increment = (x) => x + 1;
 - lift(increment)([2]);
 - // => [3]
 - [2].map(increment);
 - // => [3]
 















 
 
 





 
 
 
 