JavaScript 函数柯里化的学习笔记

一. 函数柯里化的定义

函数柯里化,Function currying,又称部分求值,指的是逐步传参,逐步求解的过程。

二. 函数柯里化的实现

一个Curry函数首先会接受一些参数,接受参数之后,该函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

如下:

var add = (function() {
    var numArr = [];

    return function() {
        if(arguments.length === 0) {
            var result = 0;
            for(var i = 0, len = numArr.length; i < len; i++) {
                result += numArr[i];
            }
            return result;
        } else {
            // numArr.push(arguments);
            Array.prototype.push.apply(numArr, arguments);
        }
    }
})();

/* =============== 客户端调用 =============== */
add(21);
add(2);

console.log(add()); // 23

三. 通用的柯里化函数

柯里化的操作可以概括为:

接受一个函数;
返回一个只接收一个参数的函数。
通用的柯里化函数可以如下:

var currying = function(fn) {
    var args = [];

    return function() {
        if(arguments.length === 0) {
            // 进行真正的求值计算
            return fn.apply(this, args);
        } else {
            // 保存调用的所有参数
            Array.prototype.push.apply(args, arguments);
            return arguments.callee;
        }
    }
};

那么上面的add函数可以改写成如下:

var add = (function() {
    var result = 0;
    return function() {
        for(var i = 0, len = arguments.length; i < len; i++) {
            result += arguments[i];
        }
        return result;
    }
})();
调用结果如下:

/* =============== 客户端调用 =============== */
var addCurrying = currying(add); // 转换成currying函数
addCurrying(21);
addCurrying(2);

console.log(addCurrying()); // 23

四. 反柯里化

反柯里化与柯里化相反,就是把原来已经固定的参数或者this上下文等当作参数延迟到未来传递。

反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用。更通俗的解释说反柯里化是 函数的借用,是函数能够接受处理其他对象,通过借用泛化、扩大了函数的使用范围。

反柯里化的三种写法如下:

4.1 写法一:

var uncurrying= function (fn) {
    return function () {
        var context = [].shift.call(arguments);
        return fn.apply(context, arguments);
    }
};

4.2 写法二:

var uncurrying = function(fn) {
    return function() {
        return Function.prototype.call.apply(fn, arguments);
    }
}

4.3 写法三:

var uncurrying = Function.prototype.bind.bind(Function.prototype.call);
4.4 反柯里化的实际调用示例:

/* =============== 客户端调用 =============== */
var push = uncurrying(Array.prototype.push); // 反柯里化

var arr = {};
push( arr , ["Bob" , "Jenny" , "Tom"] );

console.log(arr); // Object {0: "Bob", 1: "Jenny", 2: "Tom", length: 3}

五. 柯里化的适用场景

当一个函数传递的参数绝大多数是相同的,且函数结果的可以推迟到参数耗尽时才计算,那么该函数就适合使用柯里化。

六. 柯里化的性能分析

柯里化肯定会有一些性能开销,具体性能分析如下:

存取 arguments 对象通常要比存取命名参数要慢一些;
一些老版本的浏览器在 arguments.length 的实现上相当慢;
使用 fn.apply() 和 fn.call() 要比直接调用 fn() 要慢点;
创建大量嵌套作用域和闭包会带来开销。
七. 总结

函数柯里化允许和鼓励你分隔复杂功能变成更小更容易分析的部分。这些小的逻辑单元显然是更容易理解和测试的,然后你的应用就会变成干净而整洁的组合,由一些小单元组成的组合。

但是函数柯里化也会带来一些性能开销。在项目开发中斟酌使用。

时间: 2024-09-25 01:36:21

JavaScript 函数柯里化的学习笔记的相关文章

JavaScript函数柯里化详解_javascript技巧

什么是柯里化 柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(译注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数. 柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callba

Javascript闭包与函数柯里化浅析_基础知识

闭包和柯里化都是JavaScript经常用到而且比较高级的技巧,所有的函数式编程语言都支持这两个概念,因此,我们想要充分发挥出JavaScript中的函数式编程特征,就需要深入的了解这两个概念,闭包事实上更是柯里化所不可缺少的基础. 一.柯里化的概念 在计算机科学中,柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由Christopher Strachey以逻辑学家 Haskell Curry 命名的,尽管

浅谈JS中的bind方法与函数柯里化_javascript技巧

绑定函数bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值.不同于call和apply只是单纯地设置this的值后传参,它还会将所有传入bind()方法中的实参(第一个参数之后的参数)与this一起绑定. 关于这个特性看<JS权威指南>原文的例子: var sum = function(x,y) { return x + y }; var succ = sum.bind(null, 1); //让this指向null,其后的实参也会作为实参传入被绑定的函数sum

Swift函数柯里化(Currying)简谈

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多个参数的函数划分为若干个"嵌套"的单一参数的函数. 这样说谁也听不懂,我们结合一个例子给大家简单说说. 我们需要定义一个函数A,该函数返回一个函数B,函数B创建一只大蜘蛛.为什么要间接返回大蜘蛛,因为本猫最怕大蜘蛛,所以不敢直接返回大蜘蛛 ;) 首先是蜘蛛的类: class Spider:

JS编程建议——75:函数柯里化

建议75:函数柯里化柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回一个新函数,这个新函数能够接受原函数的参数.下面可以通过例子来帮助理解.function adder(num) { return function(x) { return num + x; } }var add5 = adder(5);var add6 = adder(6);print(add5(1)); // 6print(add6(1)); //7函数adder接受一个参数,并返回一个函数,这个返回的函数可

JavaScript函数的定义和调用学习笔记

JavaScript函数的定义 函数的定义使用关键字 function,语法如下: function funcName ([parameters]){     statements;     [return表达式;] } 函数各部分的含义: •funcName为函数名.函数名可由开发者自行定义,与变量的命名规则相同. •parameters为函数的参数.在调用函数时,需将实际数据传递给参数列表以完成函数的特定功能.参数列表中可定义一个或多个参数,多个参数用逗号" , "分开,当然,参数

javascript中利用柯里化函数实现bind方法_javascript技巧

柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用:bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @param cont

深入剖析JavaScript中的函数currying柯里化_javascript技巧

curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名).   柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程.  柯里化一个求和函数 按照分步求值,我们看一个简单的例子 var concat3Words = function (a, b, c) {

深入解析JavaScript中函数的Currying柯里化_javascript技巧

引子先来看一道小问题: 有人在群里出了到一道题目: var s = sum(1)(2)(3) ....... 最后 alert(s) 出来是6  var s = sum(1)(2)(3)(4) ....... 最后 alert(s) 出来是10  问sum怎么实现? 刚看到题目,我第一反应是sum返回的是一个function,但是没有最终实现,印象中看到过类似的原理,但是记不清了.   后来同事说,这个是叫柯里化, 实现方法比较巧妙:   function sum(x){ var y = fun