javascript之Partial Application學(xué)習(xí)
更新時(shí)間:2013年01月10日 09:05:50 作者:
在數(shù)學(xué)中,一個(gè)函數(shù)是描述每個(gè)輸入值對(duì)應(yīng)唯一輸出值的這種對(duì)應(yīng)關(guān)系,符號(hào)為 f(x)。例如,表達(dá)式 f(x)=x2表示了一個(gè)函數(shù) f,其中每個(gè)輸入值x都與唯一輸出值x2相聯(lián)系
這一次來學(xué)習(xí)一下Partial Application。我們先看一下函數(shù)的介紹,在維基上有簡單的介紹:
在數(shù)學(xué)中,一個(gè)函數(shù)是描述每個(gè)輸入值對(duì)應(yīng)唯一輸出值的這種對(duì)應(yīng)關(guān)系,符號(hào)為 f(x)。例如,表達(dá)式 f(x)=x2表示了一個(gè)函數(shù) f,其中每個(gè)輸入值x都與唯一輸出值x2相聯(lián)系。
因此,如果一個(gè)輸入值為3,那么它所對(duì)應(yīng)的輸出值為9。而g(x,y) = xy有兩個(gè)參量x和y,以乘積xy為值。上面描述了函數(shù)(為方便假設(shè)x,y都是int),并且給出了函數(shù)的兩個(gè)例子,先換一種方式來看,f(x)可以表示為:x -> y(x2),即經(jīng)經(jīng)過f到x2的映射,寫成 int -> int。
接受一個(gè)int 返回一個(gè)int。再看g(x,y)可以表示為:x -> y -> z(xy)。即x,y經(jīng)過g的映射到z,寫成 int -> int -> int。我們看g(x,y)函數(shù),用javascript來實(shí)現(xiàn)一下:
function g(x,y){
return x*y;
}
很完美啊,很接近數(shù)學(xué)定義。它依次接受兩個(gè)參數(shù),x與y。并且返回它們兩個(gè)的乘積。但是當(dāng)x是個(gè)常數(shù),比如x=n(n是一個(gè)自然數(shù))。那么g(n,y)=ny。這就變成一個(gè)常數(shù)與一個(gè)變量的乘積,它接受一個(gè)參數(shù)y返回ny,即y -> z(ny) 的映射,寫成 int -> int。因此,我們可以這樣來理解上面的工作,g(x,y)是接受一個(gè)參數(shù)int,并且返回一個(gè)函數(shù) int ->int 。這個(gè)返回的函數(shù)只接受一個(gè)int 并且返回一個(gè)int。來用javascript表示一下:
var h = g(2);
這里的h表示函數(shù)h(y)=2y。這樣就有h(5)=10,h(13)=26等。
h(5);
h(13);
這個(gè)技術(shù)是把需要多個(gè)參數(shù)的函數(shù)形式轉(zhuǎn)變?yōu)榻邮軉蝹€(gè)參數(shù)的函數(shù)鏈,它通常叫做Curring,這是為了紀(jì)念Haskell Curry而起的名字,但他并不是第一個(gè)提出的1。但是很遺憾的是javascript并不支持這樣的特性。所以要實(shí)現(xiàn)這樣的特性需要做一些工作,這些工作并不復(fù)雜。主要是把參數(shù)存儲(chǔ)起來,等待調(diào)用函數(shù)鏈上的下一個(gè)函數(shù)時(shí)拿出前邊參數(shù)繼續(xù)傳遞給鏈上的下一個(gè)函數(shù),直到最后得到返回值。先看一下下面的代碼:
function atarr(a,index){
var index=index||0,args = new Array(a.length - index);
for(var i in a){
if(i>=index) args[i-index]=a[i];
}
return args;
}
function m(scope,fn){
if(arguments.length<3) return fn.call(scope);
var p = atarr(arguments,2);
return function(){
var args = atarr(arguments);
return fn.apply(scope,p.concat(args));
}
}
測試代碼:
var plus = function(a,b){
return a+b;
};
var plus2 = m(null,plus,2);
console.log(plus2(10));
console.log(plus2(0));
//結(jié)果
12
2
這樣我們的目標(biāo)已經(jīng)實(shí)現(xiàn)啦。在上面的atarr函數(shù)是將arguments對(duì)象中指定位置開始的參數(shù)取出并且保存到一個(gè)數(shù)組中。m函數(shù)就是主角,它完成了前面定義的任務(wù),實(shí)現(xiàn)了保存函數(shù)鏈上的參數(shù)并且返接受余下參數(shù)的函數(shù)。測試代碼中的plus函數(shù)原先接受a,b兩個(gè)參數(shù)并返回a與b之和,即 int -> int -> int,而plus2則變成了接受一個(gè)參數(shù)b與2相加,并返回2與b之和,即 int -> int。
通過上面的一些工作,我們實(shí)現(xiàn)了javascript中的Partial Application,在dojo框架中hitch2實(shí)現(xiàn)了域綁定和partial。有興趣可以讀一下它的源碼,也是非常簡單明了的。
在數(shù)學(xué)中,一個(gè)函數(shù)是描述每個(gè)輸入值對(duì)應(yīng)唯一輸出值的這種對(duì)應(yīng)關(guān)系,符號(hào)為 f(x)。例如,表達(dá)式 f(x)=x2表示了一個(gè)函數(shù) f,其中每個(gè)輸入值x都與唯一輸出值x2相聯(lián)系。
因此,如果一個(gè)輸入值為3,那么它所對(duì)應(yīng)的輸出值為9。而g(x,y) = xy有兩個(gè)參量x和y,以乘積xy為值。上面描述了函數(shù)(為方便假設(shè)x,y都是int),并且給出了函數(shù)的兩個(gè)例子,先換一種方式來看,f(x)可以表示為:x -> y(x2),即經(jīng)經(jīng)過f到x2的映射,寫成 int -> int。
接受一個(gè)int 返回一個(gè)int。再看g(x,y)可以表示為:x -> y -> z(xy)。即x,y經(jīng)過g的映射到z,寫成 int -> int -> int。我們看g(x,y)函數(shù),用javascript來實(shí)現(xiàn)一下:
復(fù)制代碼 代碼如下:
function g(x,y){
return x*y;
}
很完美啊,很接近數(shù)學(xué)定義。它依次接受兩個(gè)參數(shù),x與y。并且返回它們兩個(gè)的乘積。但是當(dāng)x是個(gè)常數(shù),比如x=n(n是一個(gè)自然數(shù))。那么g(n,y)=ny。這就變成一個(gè)常數(shù)與一個(gè)變量的乘積,它接受一個(gè)參數(shù)y返回ny,即y -> z(ny) 的映射,寫成 int -> int。因此,我們可以這樣來理解上面的工作,g(x,y)是接受一個(gè)參數(shù)int,并且返回一個(gè)函數(shù) int ->int 。這個(gè)返回的函數(shù)只接受一個(gè)int 并且返回一個(gè)int。來用javascript表示一下:
復(fù)制代碼 代碼如下:
var h = g(2);
這里的h表示函數(shù)h(y)=2y。這樣就有h(5)=10,h(13)=26等。
復(fù)制代碼 代碼如下:
h(5);
h(13);
這個(gè)技術(shù)是把需要多個(gè)參數(shù)的函數(shù)形式轉(zhuǎn)變?yōu)榻邮軉蝹€(gè)參數(shù)的函數(shù)鏈,它通常叫做Curring,這是為了紀(jì)念Haskell Curry而起的名字,但他并不是第一個(gè)提出的1。但是很遺憾的是javascript并不支持這樣的特性。所以要實(shí)現(xiàn)這樣的特性需要做一些工作,這些工作并不復(fù)雜。主要是把參數(shù)存儲(chǔ)起來,等待調(diào)用函數(shù)鏈上的下一個(gè)函數(shù)時(shí)拿出前邊參數(shù)繼續(xù)傳遞給鏈上的下一個(gè)函數(shù),直到最后得到返回值。先看一下下面的代碼:
復(fù)制代碼 代碼如下:
function atarr(a,index){
var index=index||0,args = new Array(a.length - index);
for(var i in a){
if(i>=index) args[i-index]=a[i];
}
return args;
}
function m(scope,fn){
if(arguments.length<3) return fn.call(scope);
var p = atarr(arguments,2);
return function(){
var args = atarr(arguments);
return fn.apply(scope,p.concat(args));
}
}
測試代碼:
復(fù)制代碼 代碼如下:
var plus = function(a,b){
return a+b;
};
var plus2 = m(null,plus,2);
console.log(plus2(10));
console.log(plus2(0));
//結(jié)果
12
2
這樣我們的目標(biāo)已經(jīng)實(shí)現(xiàn)啦。在上面的atarr函數(shù)是將arguments對(duì)象中指定位置開始的參數(shù)取出并且保存到一個(gè)數(shù)組中。m函數(shù)就是主角,它完成了前面定義的任務(wù),實(shí)現(xiàn)了保存函數(shù)鏈上的參數(shù)并且返接受余下參數(shù)的函數(shù)。測試代碼中的plus函數(shù)原先接受a,b兩個(gè)參數(shù)并返回a與b之和,即 int -> int -> int,而plus2則變成了接受一個(gè)參數(shù)b與2相加,并返回2與b之和,即 int -> int。
通過上面的一些工作,我們實(shí)現(xiàn)了javascript中的Partial Application,在dojo框架中hitch2實(shí)現(xiàn)了域綁定和partial。有興趣可以讀一下它的源碼,也是非常簡單明了的。
您可能感興趣的文章:
相關(guān)文章
標(biāo)題過長使用javascript按字節(jié)截取字符串
在網(wǎng)頁展示中經(jīng)常會(huì)碰到,標(biāo)題過長,需要截取字符串,用CSS的實(shí)現(xiàn)的話各種兼容問題,下面為大家介紹下javascript如何按字節(jié)截取字符串2014-04-04
使用JavaScript計(jì)算前一天和后一天的思路詳解
這篇文章主要介紹了使用JavaScript計(jì)算前一天和后一天的思路,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
js對(duì)象實(shí)現(xiàn)數(shù)據(jù)分頁效果
這篇文章主要為大家詳細(xì)介紹了js對(duì)象實(shí)現(xiàn)數(shù)據(jù)分頁效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
ionic組件ion-tabs選項(xiàng)卡切換效果實(shí)例
這篇文章主要為大家詳細(xì)介紹了ionic組件ion-tabs選項(xiàng)卡切換效果實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
requireJS模塊化實(shí)現(xiàn)返回頂部功能的方法詳解
這篇文章主要介紹了requireJS模塊化實(shí)現(xiàn)返回頂部功能的方法,結(jié)合實(shí)例形式詳細(xì)分析了requireJS的使用步驟及返回頂部功能的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10

