hg888皇冠手机登录

javascript的currying函数介绍

九月 8th, 2019  |  www.hg888.com

// memoize: 使用memoization来缓存的通用方法
// func: 要被缓存的艺术
// context: 方法实践上下文
// Note: 方法必得是外界可访谈的,参数是可字符连串化的
function memoize (func, context) {
    function memoizeArg (argPos) { //参数表示原来方法中参数的地点
        var cache = {}; //这几个缓存的key是参数,value是实施结果
        return function () { //重临贰个函数闭包
            if (argPos == 0) {
//第贰个参数,假使参数在缓存的key中一纸空文,就推行原始函数何况存款和储蓄施行结果
                if (!(arguments[argPos] in cache)) {
                    cache[arguments[argPos]] = func.apply(context,
arguments);
                }
                return cache[arguments[argPos]];
            }
            else {
//不是第四个参数,假设参数在缓存的key中一纸空文,就递归实践memoizeArg方法,原始方法中参数的职位-1
                if (!(arguments[argPos] in cache)) {
                    cache[arguments[argPos]] = memoizeArg(argPos –
1);
                }
                return cache[arguments[argPos]].apply(this,
arguments);
            }
        }
    }
    var arity = func.arity || func.length;
//func参数的尺寸,javascript中用length属性,别的的用arity属性
    return memoizeArg(arity – 1); //从最终三个参数开始递归
}

复制代码 代码如下:

复制代码 代码如下:

function sum(){
var result=0;
for(var i=0, n=arguments.length; i<n; i++){
result += arguments[i];
}
return result;
};
var curry = function(fn){//原函数的参数为函数
return
function(args){//内部函数的参数为数组,由于当下试行,由此一贯到第三重去
var self= arguments.callee;//把自家保存起来
return function(){ //那才是第一回调用的函数
if(arguments.length){//若是还恐怕有要加上的参数
[].push.apply(args,arguments);
return self(args);
}
else return fn.apply(this,args);//执行
}
}([]);
};
var sum2= curry(sum);
sum2= sum2(1,2,3);
sum2= sum2(4,5,6);
sum2= sum2(7,8,9);
alert(sum2());

复制代码 代码如下:

var fibonacci = function() {
var memo = [0, 1];
var fib = function (n) {
var result = memo[n];
if (typeof result !== ‘number’) {
result = fib(n – 1) + fib(n – 2);
memo[n] = result;
}
return result;
};
return fib;
}();

举个例子,我们想要一个递归函数来计量 Fibonacci 数列。三个 Fibonacci
数字是事先五个 Fibonacci 数字之和。最前头的多个数字是 0 和 1。

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([]);
}

复制代码 代码如下:

// 0: 0
// 1: 1
// 2: 1
// 3: 2
// 4: 3
// 5: 5
// 6: 8
// 7: 13
// 8: 21
// 9: 34
// 10: 55

复制代码 代码如下:

复制代码 代码如下:

图片 1

var fibonacci = function (n) {
return n < 2 ? n : fibonacci(n – 1) + fibonacci(n – 2);
};

// 0: 0
// 1: 1
// 2: 1
// 3: 2
// 4: 3
// 5: 5
// 6: 8
// 7: 13
// 8: 21
// 9: 34
// 10: 55

复制代码 代码如下:

复制代码 代码如下:

啊,差异是平昔把数组当作键来用,可是要潜心函数里的arguments是js解释器落成的八个非同小可指标,并非确实的数组,所以要转移一下……
ps: 原来的参数包罗方法名称和上下文援用:fib.fib_memo =
Memoize(‘fib_memo’,
fib),但实际currying生成的函数里能够用this直接援用上层对象,更目不暇接的例证能够参见JohnResig的makeClass,所以本人改成直接传函数引用:fib.fib_memo =
Memoize(fib.fib_memo)
这么写看上去如同很可相信,由参数组成的数组不是举世无双的么。但事实上,数组之所以能当做js对象的脾气名称来利用,是因为它被当作字符串管理了,也正是说假如你给函数字传送的参数是这般:(1,2,3),
cache对象就能够是以此样子:{ “1,2,3″: somedata
},假诺您的参数里有对象,比如:(1,2,{i:”yy”}),实际的键值会是:”1,2,[object
Object]“,所以那跟把数组拼接成字符串的格局其实并未有分别……
示例:

realazy在blog上交给了多个JavaScript
Memoization的落到实处,Memoization就是函数重返值的缓存,举例贰个函数参数与重回结果一一对应的hash列表,wiki上实在也可能有详实表明,笔者不细说了,只切磋一下具体完毕的标题,realazy文中的代码有局地标题,比方直接用参数拼接成的字符串作为查询缓存结果的key,假如参数里包含对象或数组的话,就很难保障独一的key,还也会有1楼争论里关系的:[221,3]和[22,13]那样的参数也相当的小概区分。
那就是说来改写一下,首先依旧用hash表来贮存缓存数据:

复制代码 代码如下:

function Memoize(fn){
    var cache = {};
    return function(){
        var key = [];
        for( var i=0, l = arguments.length; i < l; i++ )
            key.push(arguments[i]);
        if( !(key in cache) )
            cache[key] = fn.apply(this, arguments);
        return cache[key];
    };
}

复制代码 代码如下:

var fib = {
temp: function(n){
for(var i=0;i<10000;i++)
n=n+2;
return n;
}
}
Memoize(fib,”temp”); //让fib.temp缓存再次回到值
fib.temp(16); //实践结果:20006,被缓存
fib.temp(20); //试行结果:两千6
fib.temp(10); //实践结果:贰仟6
fib.temp.reset(); //重新设置缓存
fib.temp(10); //实行结果:二零零一0

var myadd = add( 2 );
var total = myadd(3);

以下来自JohnHann的落到实处,这段代码引起了自己的注目,它用抢眼的点子把措施调用的结果缓存起来了。

譬喻,大家想要二个递归函数来总结 Fibonacci 数列。叁个 Fibonacci
数字是事先七个 Fibonacci 数字之和。最前头的三个数字是 0 和 1。

以此函数重回同样的结果,可是它只被调用了 29 次。大家调用了它 十三回,它本人调用了 18 次去获得此前积累的结果。
上述内容出自:

sum2(); // 15

代码分析:

var fib = {
temp: function(n){
for(var i=0;i<10000;i++)
n=n+2;
return n;
}
}
Memoize(fib,”temp”); //让fib.temp缓存重回值
fib.temp(16); //实践结果:三千6,被缓存
fib.temp(20); //试行结果:三千6
fib.temp(10); //试行结果:三千6
fib.temp.reset(); //重新载入参数缓存
fib.temp(10); //试行结果:20020

function Memoize(o, p) {
var f = o[p], mf, value;
var s = function(v) {return o[p]=v||mf};
((mf = function() {
(s(function(){return value})).reset = mf.reset;
return value = f.apply(this,arguments); //此处修改过,允许接受参数
}).reset = s)();
}

依旧每一遍传入多少个参数:

复制代码 代码如下:

我们在三个名称叫 memo
的数组里保存大家的积攒结果,累积结果能够遮掩在闭包中。当大家的函数被调用时,这几个函数首先看是还是不是曾经知晓总计的结果,如若已经通晓,就立即回到那些蕴藏结果。

这样是能够干活的,不过它做了好些个无谓的做事。 Fibonacci 函数被调用了 453回。大家调用了 11 次,而它自己调用了 445回去总结也许已经被刚计算过的值。假使大家让该函数具有回想成效,就能够一览了然地减小它的运算量。

eval(“var curried =” + curriedText);
return curried;
}

标签:,

Your Comments

近期评论

    功能


    网站地图xml地图