javascript currying返回函數(shù)的函數(shù)
更新時(shí)間:2009年11月09日 18:10:54 作者:
currying函數(shù)是一種返回函數(shù)的函數(shù),是閉包最偉大的應(yīng)用之一。有關(guān)閉包更詳細(xì)的定義可參見(jiàn)這里與這里。如下currying函數(shù)的一種定義。
最早期的curry函數(shù)有點(diǎn)多態(tài)的意味,就是根據(jù)函數(shù)參數(shù)在內(nèi)部選用分支:
//http://www.openlaszlo.org/pipermail/laszlo-user/2005-March/000350.html
// ★★On 8 Mar 2005, at 00:06, Steve Albin wrote:
function add(a, b) {
if (arguments.length < 1) {
return add;
} else if (arguments.length < 2) {
return function(c) { return a + c }
} else {
return a + b;
}
}
var myadd = add( 2 );
var total = myadd(3);
日本的一個(gè)先行者可能在未搞清arguments也能用Array的原生方法轉(zhuǎn)換為數(shù)組的時(shí)候,用非常復(fù)雜的正則與eval搞出一個(gè)更接近現(xiàn)代currying意味的函數(shù)。
function curry(fun) {
if (typeof fun != 'function') {
throw new Error("The argument must be a function.");
}
if (fun.arity == 0) {
throw new Error("The function must have more than one argument.");
}
var funText = fun.toString();
var args = /function .*\((.*)\)(.*)/.exec(funText)[1].split(', ');
var firstArg = args.shift();
var restArgs = args.join(', ');
var body = funText.replace(/function .*\(.*\) /, "");
var curriedText =
"function (" + firstArg + ") {" +
"return function (" + restArgs + ")" + body +
"}";
eval("var curried =" + curriedText);
return curried;
}
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
接著是閉包的流行,與數(shù)組轉(zhuǎn)換arguments的技術(shù)的發(fā)現(xiàn),現(xiàn)代currying函數(shù)終于粉墨登場(chǎng),就好像15~17世紀(jì)大航海時(shí)代的地理大發(fā)現(xiàn),javascript的世界突然間開(kāi)闊了許多。
//一個(gè)簡(jiǎn)單的現(xiàn)代currying函數(shù)
function curry (fn, scope) {
var scope = scope || window;
var args = [];
for (var i=2, len = arguments.length; i < len; ++i) {
args.push(arguments[i]);
};
return function() {
fn.apply(scope, args);
};
}
一般的currying函數(shù)只有兩重,執(zhí)行情況如下,第一次執(zhí)行參數(shù)不足返回內(nèi)部函數(shù),第二次執(zhí)行才最終完成。不過(guò)針對(duì)這參數(shù),我們還是可以做一些文章??慈缦潞瘮?shù):
function sum(){
var result=0;
for(var i=0, n=arguments.length; i<n; i++){
result += arguments[i];
}
return result;
}
alert(sum(1,2,3,4,5)); // 15
這就沒(méi)有所謂的參數(shù)不足問(wèn)題,傳入一個(gè)參數(shù),它也計(jì)算。但不傳入?yún)?shù)呢?無(wú)錯(cuò),區(qū)別在于有沒(méi)有參數(shù)。我們可以讓它不斷執(zhí)行自身,如果參數(shù)存在的情況下。最后在沒(méi)有參數(shù)的情況下,一次過(guò)執(zhí)行。換言之,前面的步驟是用于儲(chǔ)存參數(shù)。
var sum2= curry(sum);
sum2= sum2(1)(2)(3)(4)(5);
sum2(); // 15
比起一般的currying函數(shù),這有點(diǎn)難度。具體看注解:
var curry= function(fn){//原函數(shù)的參數(shù)為函數(shù)
return function(args){//內(nèi)部函數(shù)的參數(shù)為數(shù)組,由于立即執(zhí)行,因此直接到第三重去
//args是相對(duì)于第三重內(nèi)部函數(shù)可是全局變量
var self= arguments.callee;//把自身保存起來(lái)(就是那個(gè)數(shù)組為參數(shù)的第二重函數(shù))
return function(){ //這才是第二次調(diào)用的函數(shù)
if(arguments.length){//如果還有要添加的參數(shù)
[].push.apply(args,arguments);//apply把當(dāng)前傳入的所有參數(shù)放進(jìn)args中
return self(args);
}else{
return fn.apply(this,args);//apply的第二參數(shù)為數(shù)組
}
}
}([]);
};
或者每次傳入多個(gè)參數(shù):
但上面的函數(shù)有不足之處,最后怎么也要放個(gè)括號(hào),我們想只要參數(shù)足夠就返回結(jié)果,多出的參數(shù)忽略。改進(jìn)如下:
function curry(f) {
if (f.length == 0) return f;
function iterate(args) {
if (args.length <= f.length)
return f.apply(null, args);
return function () {
return iterate(args.concat(Array.prototype.slice.call(arguments)));
};
}
return iterate([]);
}
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
復(fù)制代碼 代碼如下:
//http://www.openlaszlo.org/pipermail/laszlo-user/2005-March/000350.html
// ★★On 8 Mar 2005, at 00:06, Steve Albin wrote:
function add(a, b) {
if (arguments.length < 1) {
return add;
} else if (arguments.length < 2) {
return function(c) { return a + c }
} else {
return a + b;
}
}
var myadd = add( 2 );
var total = myadd(3);
日本的一個(gè)先行者可能在未搞清arguments也能用Array的原生方法轉(zhuǎn)換為數(shù)組的時(shí)候,用非常復(fù)雜的正則與eval搞出一個(gè)更接近現(xiàn)代currying意味的函數(shù)。
復(fù)制代碼 代碼如下:
function curry(fun) {
if (typeof fun != 'function') {
throw new Error("The argument must be a function.");
}
if (fun.arity == 0) {
throw new Error("The function must have more than one argument.");
}
var funText = fun.toString();
var args = /function .*\((.*)\)(.*)/.exec(funText)[1].split(', ');
var firstArg = args.shift();
var restArgs = args.join(', ');
var body = funText.replace(/function .*\(.*\) /, "");
var curriedText =
"function (" + firstArg + ") {" +
"return function (" + restArgs + ")" + body +
"}";
eval("var curried =" + curriedText);
return curried;
}
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
接著是閉包的流行,與數(shù)組轉(zhuǎn)換arguments的技術(shù)的發(fā)現(xiàn),現(xiàn)代currying函數(shù)終于粉墨登場(chǎng),就好像15~17世紀(jì)大航海時(shí)代的地理大發(fā)現(xiàn),javascript的世界突然間開(kāi)闊了許多。
復(fù)制代碼 代碼如下:
//一個(gè)簡(jiǎn)單的現(xiàn)代currying函數(shù)
function curry (fn, scope) {
var scope = scope || window;
var args = [];
for (var i=2, len = arguments.length; i < len; ++i) {
args.push(arguments[i]);
};
return function() {
fn.apply(scope, args);
};
}
一般的currying函數(shù)只有兩重,執(zhí)行情況如下,第一次執(zhí)行參數(shù)不足返回內(nèi)部函數(shù),第二次執(zhí)行才最終完成。不過(guò)針對(duì)這參數(shù),我們還是可以做一些文章??慈缦潞瘮?shù):
復(fù)制代碼 代碼如下:
function sum(){
var result=0;
for(var i=0, n=arguments.length; i<n; i++){
result += arguments[i];
}
return result;
}
alert(sum(1,2,3,4,5)); // 15
這就沒(méi)有所謂的參數(shù)不足問(wèn)題,傳入一個(gè)參數(shù),它也計(jì)算。但不傳入?yún)?shù)呢?無(wú)錯(cuò),區(qū)別在于有沒(méi)有參數(shù)。我們可以讓它不斷執(zhí)行自身,如果參數(shù)存在的情況下。最后在沒(méi)有參數(shù)的情況下,一次過(guò)執(zhí)行。換言之,前面的步驟是用于儲(chǔ)存參數(shù)。
var sum2= curry(sum);
sum2= sum2(1)(2)(3)(4)(5);
sum2(); // 15
比起一般的currying函數(shù),這有點(diǎn)難度。具體看注解:
復(fù)制代碼 代碼如下:
var curry= function(fn){//原函數(shù)的參數(shù)為函數(shù)
return function(args){//內(nèi)部函數(shù)的參數(shù)為數(shù)組,由于立即執(zhí)行,因此直接到第三重去
//args是相對(duì)于第三重內(nèi)部函數(shù)可是全局變量
var self= arguments.callee;//把自身保存起來(lái)(就是那個(gè)數(shù)組為參數(shù)的第二重函數(shù))
return function(){ //這才是第二次調(diào)用的函數(shù)
if(arguments.length){//如果還有要添加的參數(shù)
[].push.apply(args,arguments);//apply把當(dāng)前傳入的所有參數(shù)放進(jìn)args中
return self(args);
}else{
return fn.apply(this,args);//apply的第二參數(shù)為數(shù)組
}
}
}([]);
};
或者每次傳入多個(gè)參數(shù):
但上面的函數(shù)有不足之處,最后怎么也要放個(gè)括號(hào),我們想只要參數(shù)足夠就返回結(jié)果,多出的參數(shù)忽略。改進(jìn)如下:
復(fù)制代碼 代碼如下:
function curry(f) {
if (f.length == 0) return f;
function iterate(args) {
if (args.length <= f.length)
return f.apply(null, args);
return function () {
return iterate(args.concat(Array.prototype.slice.call(arguments)));
};
}
return iterate([]);
}
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
相關(guān)文章
JS將光標(biāo)聚焦在文本最后的實(shí)現(xiàn)代碼
這篇文章主要介紹了JS將光標(biāo)聚焦在文本最后的方法,需要的朋友可以參考下2014-03-03
關(guān)于Javascript作用域鏈的八點(diǎn)總結(jié)
其實(shí)吧,關(guān)于作用域鏈相關(guān)的文章我也看了不少,但是我一直也沒(méi)能做一個(gè)詳細(xì)的總結(jié),今天把我看到的一些東西,結(jié)合自己的想法,總結(jié)成以下8個(gè)點(diǎn)2013-12-12
JS 對(duì)象屬性相關(guān)(檢查屬性、枚舉屬性等)
這篇文章主要介紹了JS 對(duì)象屬性相關(guān)(檢查屬性、枚舉屬性等),需要的朋友可以參考下2015-04-04
JavaScript代碼簡(jiǎn)單實(shí)現(xiàn)求楊輝三角給定行的最大值
求楊輝三角給定行的最大值的的方法或許有很多,下面使用js代碼簡(jiǎn)單實(shí)現(xiàn)下,感興趣的朋友可以參考下2013-10-10
alixixi runcode.asp的代碼不錯(cuò)的應(yīng)用
alixixi runcode.asp的代碼不錯(cuò)的應(yīng)用...2007-08-08
如何寫一個(gè)通用的JavaScript效果庫(kù)!(2/2)
如何寫一個(gè)通用的JavaScript效果庫(kù)!(2/2)...2007-04-04
JS實(shí)現(xiàn)的ajax和同源策略(實(shí)例講解)
下面小編就為大家分享一篇JS實(shí)現(xiàn)的ajax和同源策略的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助2017-12-12
uni-app多環(huán)境配置實(shí)現(xiàn)自動(dòng)部署的方式詳解
前后端分離開(kāi)發(fā)模式中,無(wú)論前后端都有可能區(qū)分不同的環(huán)境配置,下面這篇文章主要給大家介紹了關(guān)于uni-app多環(huán)境配置實(shí)現(xiàn)自動(dòng)部署的相關(guān)資料,需要的朋友可以參考下2022-06-06
純CSS3代碼實(shí)現(xiàn)滑動(dòng)開(kāi)關(guān)效果
CSS33D炫酷左右滑動(dòng)開(kāi)關(guān)按鈕是一款非常酷的CSS3 3D開(kāi)關(guān)按鈕,點(diǎn)擊按鈕可以左右滑動(dòng),就像開(kāi)關(guān)打開(kāi)閉合一樣的效果,通過(guò)本篇文章給大家介紹純CSS3代碼實(shí)現(xiàn)滑動(dòng)開(kāi)關(guān)效果,需要的朋友可以參考下2015-08-08

