闭包与柯里化的小题目

题目

如何实现以下函数:

add(2,5)//7
add(2)(5)//7

分析

  1. 凭直觉讲add函数的返回值有两种,一种是数值,一种是函数,根据参数来定
  2. 要实现第二种效果的时候,返回值就是函数,那么如何把第一个参数传进返回函数中(就是闭包的应用),其实原理都很简单
  3. 似乎有点柯里化函数式编程的味道

Show Code

function add(){
    let sum = 0;
    if(arguments.length > 1){
        for(let i = 0;i<arguments.length;i++){
            sum += Number(arguments[i])||0;
        }
        return sum;
    }else{
        sum += arguments[0];
        return function(b){return sum+b}
    }   
}

这里做了一下简单的参数控制,当参数很多的时候也是可以加的,O(∩_∩)O哈哈~,比如add(1,2,3,4,5),但是如何实现add(1)(2)(3)(4)(5) 呢?
就知道你比别人多想一步,就是有没有办法把返回的函数也能变成值呢,有啊,重载toString()吧,当一个对象转换成原始值时,先查看对象是否有valueOf方法,如果有并且返回值是一个原始值,那么直接返回这个值,否则没有valueOf或返回的不是原始值,那么调用toString方法,返回字符串表示。看完这个你基本就会了柯里化了,了解更多扩展阅读

function add(){
    let sum = 0;
    if(arguments.length > 1){
        for(let i = 0;i<arguments.length;i++){
            sum += Number(arguments[i])||0;
        }
        return sum;
    }else{
        sum += arguments[0];
        let fn = function(b){return add(sum+b)}
        fn.toString = function(){return sum+''};
        fn.valueOf = function(){return sum};
        return fn;
    }   
}

One more Think

柯里化,把一批参数分多次传递这个操作叫curry.比如写个柯里化函数把下面这个函数转换成上面的效果

function sum4(a,b,c,d){return a+b+c+d;}

代码如下:

var curry = function(final, arity) {
    var curried = function() {
        // this是每次的参数列表
        // 每次slice()保证curry后的函数仍然是无状态的
        var new_args = this.slice(); 
        for(arg_key in arguments) {
            new_args.push(arguments[arg_key]);
        }

        if (new_args.length >= arity) {
            return final.apply(null, new_args);
        } else {
            return curried.bind(new_args);
        }
    };

    return curried.bind([]);
};

var sum4 = function(a,b,c,d) { return a+b+c+d; };

var curried = curry(sum4, sum4.length);

console.log(curried(1,2,3)(4));
// -> 10
console.log(curried(1)(2,3)(4));
// -> 10

这有点让我想到之前的一个面试题,跟这个差不多,只不过跟promise扯到一起了。问题就是如何把nodeCallbackStyle【function(err,args….)】转成promise,这个的确是这个很棒的问题,其实就是promisefy。本质就是个闭包传递。

function promisfy(func){
    return function(){
        var args = [].slice.call(arguments);
        return new promise((resolve,reject)=>{
            function callback(err,data){
                if(err){reject(err);}
                else{resolve(data);}
            }
            args.push(callback);
            func.apply(func,args);
        })
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值