转载请注明出处:http://www.cnblogs.com/shamoyuu/p/currying.html

什么是js函数的currying /柯里化?

说到js的柯里化,相信很多朋友都会头大。或者不是很清楚。我今天简单的给大家介绍一下。

我用一句话总结函数柯里化,js柯里化是逐步传参,逐步缩小函数的适用范围,逐步求解的过程

可能对这句话你不是很清楚,那么,我们来看个案例,简单说明一下:

需求:我们写一个函数,将函数的几个参数相加,返回结果!那我们写的函数如下

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

函数柯里化呢?是分部求解,先传一个a参数,再传一个b参数,再传一个c参数,最后将这三个参数相加!

var concat3WordsCurrying = function(a) {
    return function (b) {
        return function (c) {
            return a+b+c;
        };
    };
};

我们看输出结果:

console.log(concat3Words("foo ","bar ","baza"));            // foo bar baza
console.log(concat3WordsCurrying("foo "));                  // [Function]
console.log(concat3WordsCurrying("foo ")("bar ")("baza"));  // foo bar baza 函数链式调用

柯里化案例

上面的需求我们稍微变一下。现在我们更进一步,如果要求可传递的参数不止3个,可以传任意多个参数,当不传参数时输出结果?那现在我们用柯里化来简单的实现一下:

var adder = function () {
    var _args = [];
    return function () {
        ) {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        [].push.apply(_args, [].slice.call(arguments));
        return arguments.callee;
    }
};
var sum = adder();

console.log(sum);     // Function

sum(,)();    // 调用形式灵活,一次调用可输入一个或者多个参数,并且支持链式调用
sum();
console.log(sum());   // 1000 (加总计算) 

上面 adder是柯里化了的函数,它返回一个新的函数,新的函数接收可分批次接受新的参数,延迟到最后一次计算。我们可以任意传入参数,当不传参数的时候,输出计算结果!

基础知识普及之arguments

看到上面的柯里化实现,可能有的朋友会有点晕,其实上面也没有什么新的知识,假如你看过我之前写的文章,相信能够理解!apply,call之前都有介绍。前端干货中的第四条,也有提及!唯独arguments前面文章没有介绍。

arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments非常类似Array,但实际上又不是一个Array实例。

我们看一下下面的例子:

function f(a, b, c){
    alert(arguments.length);   // result: "2"
    a = ;
    alert(arguments[]);       // result: "100"
    arguments[] = "haorooms";
    alert(a);                  // result: "haorooms"
    alert(c);                  // result: "undefined"
    c = ;
    alert(arguments[]);       // result: "undefined"
}

f(, );

我们通常用

[].slice.call(arguments, )

将传入参数转为数组。slice是js的一个函数,关于其用法,不会的去查一下!上面的写法相当于Array.prototype.slice.call(arguments, 1);

另外,arguments对象中有一个非常有用的属性:callee。arguments.callee返回此arguments对象所在的当前函数引用。在使用函数递归调用时推荐使用arguments.callee代替函数名本身。arguments就介绍到这里!

通用的柯里化函数

下面这个是通用的柯里化函数

var currying = function (fn) {
    var _args = [];
    return function () {
        ) {
            return fn.apply(this, _args);
        }
        Array.prototype.push.apply(_args, [].slice.call(arguments));
        return arguments.callee;
    }
};

我们可以通过如下函数简单应用一下柯里化:

var multi=function () {
    ;
    , c; c = arguments[i++];) {
        total += c;
    }
    return total;
};

var sum = currying(multi);  

sum(,)();
sum();
console.log(sum());     // 1000  (空白调用时才真正计算)

增加适用性的柯里化

上面我的介绍的是柯里化延迟执行,缩小范围!还有一种是增加了函数的适用性,但同时也降低了函数的适用范围。其通用写法如下:

function currying(fn) {
    var slice = Array.prototype.slice,
    __args = slice.call(arguments, );
    return function () {
        var __inargs = slice.call(arguments);
        return fn.apply(null, __args.concat(__inargs));
    };
}

例如:

function square(i) {
    return i * i;
}
function map(handeler, list) {
    return list.map(handeler);
}
// 数组的每一项平方
map(square, [, , , , ]);
map(square, [, , , , ]);
map(square, [, , , , ]);

例子中,创建了一个map通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square。

柯里化改造:

function square(i) {
    return i * i;
}
function map(handeler, list) {
    return list.map(handeler);
}
var mapSQ = currying(map, square);
mapSQ([, , , , ]);
mapSQ([, , , , ]);
mapSQ([, , , , ]);

Function.prototype.bind 方法也是柯里化应用

与 call/apply 方法直接执行不同,bind 方法 将第一个参数设置为函数执行的上下文,其他参数依次传递给调用方法(函数的主体本身不执行,可以看成是延迟执行),并动态创建返回一个新的函数, 这符合柯里化特点。

};
var bar = function () {
    console.log(this.x);
}.bind(foo); // 绑定
bar();

完结,散花

JavaScript函数的柯里化(currying)的更多相关文章

  1. js高阶函数--判断数据类型、函数胡柯里化;

    一.判断数据类型: 常见的判断有typeof.instanceof. constructor. prototype,先来看typeof: var a = "hello world" ...

  2. 浅谈JavaScript中的柯里化函数

    首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...

  3. JavaScript函数式编程(纯函数、柯里化以及组合函数)

    JavaScript函数式编程(纯函数.柯里化以及组合函数) 前言 函数式编程(Functional Programming),又称为泛函编程,是一种编程范式.早在很久以前就提出了函数式编程这个概念了 ...

  4. Swift函数柯里化(Currying)简谈

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...

  5. JS 函数的柯里化与反柯里化

    ===================================== 函数的柯里化与反柯里化 ===================================== [这是一篇比较久之前的总 ...

  6. 关于arguments对象以及函数的柯里化;

    1.arguments对象 Arguments是个类似数组但不是数组的对象,说他类似数组是因为其具备数组相同的访问性质及方式,能够由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性 ...

  7. JS中的柯里化(currying)

    何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参 ...

  8. JS中的柯里化(currying) 转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]

    JS中的柯里化(currying) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpr ...

  9. Python进阶1---高阶函数、柯里化

    高阶函数 不相等  自定义sort函数 内建函数--高阶函数 #sort函数 def sort2(lst,key = None,reverse = False): res = [] if key is ...

随机推荐

  1. RChain总体架构图

    RChain是我研究区块链依赖发现的和我最契合的(主要是用scala写的),在架构上吞吐率和扩展性也是最好,未来是真正有可能实现在它官网上宣称的能够承载facebook一样的规模,具有和visa一样的 ...

  2. 【转】高斯-克吕格投影与UTM投影异同

    高斯-克吕格(Gauss-Kruger)投影与UTM投影(Universal Transverse Mercator,通用横轴墨卡托投影)都是横轴墨卡托投影的变种,目前一些国外的软件或国外进口仪器的配 ...

  3. Node.js在任意目录下使用express命令‘不是内部或外部命令’解决方法

    1.一开始我只能在nodejs全局目录下使用express命令建一个新的项目,建在其他任意一个目录命令行都会提示"不是内部或外部命令",导致目录会乱,目录如下. 2.尝试了一会,发 ...

  4. 安装pcntl以实现php多进程

    pcntl 扩展包一般就在php源码的ext目录下. cd ./ext/pcntl /opt/server/php5/bin/phpize ./configure \ --with-php-confi ...

  5. ABP官方文档翻译 3.7 领域事件(事件总线)

    领域事件(事件总线) 事件总线 注入IEventBus 获取默认实例 定义事件 预定义事件 处理异常 实体更改 触发事件 处理事件 处理基础事件 处理者异常 处理多个事件 注册处理者 自动 手动 取消 ...

  6. Tomcat日志与Log4j日志

    一:日志作用 更好的调试,分析问题. 普通的一个请求处理10秒钟,日志10秒钟,总共就得20秒钟,这肯定是不行的,因为日志严重影响了性能.所以,我们就有必要了解日志的实现方式,以及它是如何降低IO的时 ...

  7. Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器

    本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...

  8. Java设计模式——策略模式

    策略模式的定义: 策略模式其实特别好理解,俗话说得好,条条大路通罗马,做的都是一件事,实现的方式却可以千万种,在这种情况下,如何使得每个人都可以根据自己的喜好来选择具体的方式,在调用时可以根据不同方式 ...

  9. bzoj 1975: [Sdoi2010]魔法猪学院 [k短路]

    1975: [Sdoi2010]魔法猪学院 裸题... 被double坑死了 #include <iostream> #include <cstdio> #include &l ...

  10. boost编译随笔

    boost下载地址 编译 生成bjam.exe 1.下载boost源码,可以直接使用上面给出的1.60.0版本 2.解压下载到的boost文件,例如解压到 x:\boost_1_60_0 3.使用Vi ...