函數柯里化

函數柯里化是把接受多個參數的函數轉變成接受一個單一參數(最初函數的第一個參數),而且返回接受餘下的參數並且返回結果的新函數的技術javascript

柯里化其實自己是固定一個能夠預期的參數,並返回一個特定的函數,處理批特定的需求。這增長了函數的適用性,但同時也下降了函數的適用範圍。
php

通用定義java

function currying(fn){
    var slice = Array.prototype.slice;
    _args = slice.call(arguments,1);
    return function(){
        var _inargs = slice.call(arguments);
        return fn.apply(null,_args.concat(_inargs))
    }
    
}複製代碼

柯里化的實用性體如今不少方面:數組

提升適用性。

通用函數解決兼容性問題,可是同時也會帶來使用的不便利性,不一樣的應用場景每每要傳遞不少參數,已達到解決特定的目的.有時候應用中,會對同一個規則進行反覆使用,這樣就形成了代碼的重複性.bash

function square(i){
	return i * i;
}
function dubble(i){
	return i *= 2;
}
function map(handeler,list){
	return list.map(handeler)
}
// 數組的每一項平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);
map(square, [10, 20, 30, 40, 50]);

// 數組的每一項加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);
map(dubble, [10, 20, 30, 40, 50]);
複製代碼

例子中,建立了一個map通用函數,用於適應不一樣的應用場景。顯然,通用性不用懷疑。同時,例子中重複傳入了相同的處理函數:square和dubble。app

應用中這種可能會更多。固然,通用性的加強必然帶來適用性的減弱。可是,咱們依然能夠在中間找到一種平衡。async

看下面,咱們利用柯里化改造一下:函數

function square(i) {
    return i * i;
}

function dubble(i) {
    return i *= 2;
}

function map(handeler, list) {
    return list.map(handeler);
}

var mapSQ = currying(map, square);
mapSQ([1, 2, 3, 4, 5]);
mapSQ([6, 7, 8, 9, 10]);
mapSQ([10, 20, 30, 40, 50]);

var mapDB = currying(map, dubble);
mapDB([1, 2, 3, 4, 5]);
mapDB([6, 7, 8, 9, 10]);
mapDB([10, 20, 30, 40, 50]);複製代碼

咱們縮小了函數的適用範圍,但同時提升函數的適性。post

由此,可知柯里化不單單是提升了代碼的合理性,更重的它突出一種思想---下降適用範圍,提升適用性ui

下面再看一個例子,一個應用範圍更普遍更熟悉的例子:

function Ajax() {
    this.xhr = new XMLHttpRequest();
}

Ajax.prototype.open = function(type, url, data, callback) {
    this.onload = function() {
        callback(this.xhr.responseText, this.xhr.status, this.xhr);
    }

    this.xhr.open(type, url, data.async);
    this.xhr.send(data.paras);
}

'get post'.split(' ').forEach(function(mt) {
    Ajax.prototype[mt] = currying(Ajax.prototype.open, mt);
});

var xhr = new Ajax();
xhr.get('/articles/list.php', {},
function(datas) {
    // done(datas)    
});

var xhr1 = new Ajax();
xhr1.post('/articles/add.php', {},
function(datas) {
    // done(datas)    
});複製代碼

2 延遲執行。

柯里化的另外一個應用場景是延遲執行。不斷的柯里化,累積傳入的參數,最後執行。

看下面:

var add = function() {
    var _this = this,
    _args = arguments
    return function() {
        if (!arguments.length) {
            var sum = 0;
            for (var i = 0,c; c = _args[i++];){
                sum += c;
            }複製代碼
return sum
        } else {
            Array.prototype.push.apply(_args, arguments) return arguments.callee
        }
    }
}
add(1)(2)(3)(4)();//10複製代碼

通用的寫法:

var curry = function(fn) {
    var _args = []
    return function cb() {
        if (arguments.length == 0) {
            return fn.apply(this, _args)
        }
        Array.prototype.push.apply(_args, arguments);
        return cb;
    }
}複製代碼

上面累加的例子,能夠實驗一下怎麼寫?

3 固定易變因素。

柯里化特性決定了它這應用場景。提早把易變因素,傳參固定下來,生成一個更明確的應用函數。最典型的表明應用,是bind函數用以固定this這個易變對象。

Function.prototype.bind = function(context) {
    var _this = this,
    _args = Array.prototype.slice.call(arguments, 1);
    return function() {
        return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments)))
    }
}複製代碼
相關文章
相關標籤/搜索