一、偏函數(shù):在函數(shù)調(diào)用現(xiàn)場(chǎng)(function call-site),將實(shí)參應(yīng)用(apply) 于形參。
function getPerson(data,cb) {
ajax( "http://some.api/person", data, cb );
}
function getOrder(data,cb) {
ajax( "http://some.api/order", data, cb );
}
getOrder(data,cb) 是 ajax(url,data,cb) 函數(shù)的偏函數(shù)(partially-applied functions)。
更正式的說(shuō)法是:偏函數(shù)嚴(yán)格來(lái)講是一個(gè)減少函數(shù)參數(shù)個(gè)數(shù)(arity)的過(guò)程;這里的參數(shù)個(gè)數(shù)指的是希望傳入的形參的數(shù)量。我們通過(guò) getOrder(..) 把原函數(shù) ajax(..) 的參數(shù)個(gè)數(shù)從 3 個(gè)減少到了 2 個(gè)。
二、函數(shù)柯里化:將一個(gè)期望接收多個(gè)實(shí)參的函數(shù)拆解成連續(xù)的鏈?zhǔn)胶瘮?shù)(chained functions),每個(gè)鏈?zhǔn)胶瘮?shù)接收單一實(shí)參(實(shí)參個(gè)數(shù):1)并返回另一個(gè)接收下一個(gè)實(shí)參的函數(shù)
curriedAjax( "http://some.api/person" )
( { user: CURRENT_USER_ID } )
( function foundUser(user){ /* .. */ } );
var personFetcher = curriedAjax( "http://some.api/person" );
var getCurrentUser = personFetcher( { user: CURRENT_USER_ID } );
getCurrentUser( function foundUser(user){ /* .. */ } );
如果一個(gè)原函數(shù)期望接收 5 個(gè)實(shí)參,這個(gè)函數(shù)的柯里化形式只會(huì)接收第一個(gè)實(shí)參,并且返回一個(gè)用來(lái)接收第二個(gè)參數(shù)的函數(shù)。而這個(gè)被返回的函數(shù)又只接收第二個(gè)參數(shù),并且返回一個(gè)接收第三個(gè)參數(shù)的函數(shù)。依此類(lèi)推。
由此而知,柯里化將一個(gè)多參數(shù)(higher-arity)函數(shù)拆解為一系列的單元鏈?zhǔn)胶瘮?shù)。
一些備忘:
閉包通過(guò)詞法作用域提供“私有”狀態(tài),而對(duì)象將一切做為公共屬性暴露。
提升代碼可讀性的唯一真相就是減少表面掩蓋,讀者必須可以預(yù)見(jiàn)到每一個(gè)給定變量的行為。
使有了閉包,你就有了一些可以更改代碼的權(quán)限,而剩余的程序是受限的。當(dāng)我們凍結(jié)一個(gè)對(duì)象,代碼中沒(méi)有任何部分可以被重設(shè)。此外,一旦一個(gè)對(duì)象被凍結(jié),它不能被解凍,所以所有屬性在程序運(yùn)行期間都保持只讀。
在我想允許重新賦值但是在表層限制的地方,閉包比起對(duì)象更方便和靈活。在我不想重新賦值的地方,一個(gè)凍結(jié)的對(duì)象比起重復(fù) const 聲明在我所有的函數(shù)中更方便一些。
通過(guò)const聲明一個(gè)數(shù)組或者對(duì)象,對(duì)象的值或者數(shù)組的值是可以改變的,因?yàn)閏onst只保存了其引用的地址,只會(huì)通過(guò)地址去找值。