underscore(lodash) bind 源码疑惑

源码版本是0.1.0

function bind中的实现方式如下

bind: function(func, context){
        if(!context) return func;
        var args = _.toArray(arguments).slice(2); //出去 func,context的剩余可选参数
        return function(){
            var a = args.concat(_.toArray(arguments));   //为什么这里还需要加上所有的参数,有什么作用?
            return func.apply(context, a);
        };
    }

最后apply的时候为什么还要把之前的参数链接上去呢?

阅读 3.3k
2 个回答
bind: function(func, context){//A
        if(!context) return func;
        var args = arguments.slice(2); //[1]
        return function(){//B
            var a = args.concat(_.toArray(arguments));   //[2]
            return func.apply(context, a);
        };
    }

:[1] 此处的arguments时函数A的实际传入参数
:[2] 此处的arguments时函数B的实际传入参数,将args和函数B的实际传入参数合并作为原始传入参数-func-的调用参数,context作为上下文

作用为函数的柯里化,如下面的例子:

var bind=function(func, context){//A
        if(!context) return func;
        var args = Array.prototype.slice.apply(arguments,[2]); //[1]
        return function(){//B
            var a = args.concat(Array.prototype.slice.apply(arguments,[0]));   //[2]
            return func.apply(context, a);
        };
};
var orgFun=function(){
    var args=Array.prototype.slice.apply(arguments,[0]);
    var initvalue=this.initValue||0;
    var result=0;
    args.forEach(function(item){
        result=result+item;
    });
    return initvalue+result;
}
var boundFun=bind(orgFun,{initValue:100},1,2,3);
var result=boundFun(4,5,6);
console.log("result:"+result);//121

clipboard.png

args 是预绑定参数,实际调用时可能还会传入额外的参数,所以要加到一起。