函數的柯里化

1.函數的柯里化定義

創建已經設置好一個或多個參數的函數,基本方法是使用一個閉包返回一個函數。

2.經典面試題

實現一個add函數,完成以下功能:

console.log(add(1,2,3));   //6
console.log(add(1)(2)(3));   //6

要想創建出一個通式,很容易想到用遞歸來解決,但是遞歸需要一個結束條件,這里的結束條件怎么確定呢?
首先可以看一下console.log()函數的用法:

  • 如果傳入參數是一個函數,那么就會默認調用默認toString()方法,將函數的定義打印出來
  • 如果定義了toString()或valueOf()方法,就會調用valueOf() > toString()方法,valueOf()優先級高于toString()方法

因此這里我們可以通過自定義toString()方法來模擬結束條件,方法如下:

function add(){
    var args=Array.prototype.slice.call(arguments);
    function adder(){
        var newArgs=Array.prototype.slice.call(arguments);
        args=args.concat(newArgs);
        return adder;   //每次調用后返回自身函數對象,可以進行連續調用
    }

    adder.toString=function(){
        return args.reduce(function(previos,current){
            return previos+current;
        });
    }

    return adder;
}

主要的思路就是,利用閉包來保存每一次傳入函數的參數到args變量中,并且返回adder函數自身,最后打印的時候調用函數對象的toString方法將所有的參數相加。

3.柯里化通式

柯里化通式可以傳入一個函數和要綁定的參數,返回包裝后的函數:

function curry(func){
    var args=Array.prototype.slice.call(arguments,1);
    return function(){
        var newArgs=Array.prototype.slice.call(arguments);
        args=args.concat(newArgs);
        return func.apply(null,args);   //調用func時要用apply調用,參數都包含在數組中
    }
}

var sum=curry(function(){
    var args=Array.prototype.slice.call(arguments);
    return args.reduce(function(a,b){
        return a+b;
    });
},1);
console.log(sum(2,3));

4.實現函數柯里化的bind函數

實現函數柯里化的bind函數可以分兩次傳入參數,每次傳入的參數都會通過閉包,保存在外部函數作用域內。

function bind(func,context){
    var args=Array.prototype.slice.call(arguments,2);
    return function(){
        var newArgs=Array.prototype.slice.call(arguments);
        args=args.concat(newArgs);
        return func.apply(context,args);
    }
}

var a={
    name: 'jc',
    print: function(){
        var str=Array.prototype.join.call(arguments,' ');
        console.log(this.name+' '+str);
    }
};
var b=bind(a.print,a,'first');
b('second');   //jc first second

5.函數內部對象arguments

在函數體內可以通過arguments對象訪問參數數組,但是arguments對象只是與數組相似,并不是Array的實例,可以通過索引訪問參數,有length長度屬性,不過可以通過call和apply間接調用數組的方法:

Array.prototype.slice.call(arguments)
[].slice.call(arguments)

數組這些方法應該也是通過索引來訪問元素實現的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容