JavaScript函数式编程——柯里化
- 柯里化原理
- 如何实现柯里化
- 柯里化的应用
一、柯里化原理
柯里化:在数学和计算机科学中,柯里化是一种使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
前端使用柯里化的用途主要就应该是简化代码结构,提高系统的维护性,一个方法,只有一个参数,强制了功能的单一性,很自然就做到了功能内聚,降低耦合。
柯里化的优点:降低代码的重复,提高代码的适应性。
基于柯里化的基本原理,先将多个参数的函数执行拆分成两次传参执行:
//有如下四个参数的函数
function add(a, b, c, d){
return a + b + c + d;
}
//实现一个两次传参的固定柯里化方法
function FixedParmasCurry(fu){
var _arg = Array.prototype.slice.call(arguments,1); //获取初始柯里化时传入的参数
return function(){
var newArg = _arg.concat(Array.prototype.call(arguments,0)); //拼接当前执行的参数
return fn.apply(this, newArg);
}
}
//测试一
var foo = FixedParmasCurry(add,1,2);
console.log(foo(3,4));//
//测试二
var fun = FixedParmasCurry(add,1);
console.log(fun(2,3,4));//
但是这并没有实现真正的柯里化,真正的柯里化应该是每次传任意参数,函数经过任意次执行,直到参数传入达到函数所需要的参数时返回函数的执行结果;也可以说是函数每次传入相应的参数,返回每个执行阶段的结果。为什么这么说呢?在柯里化应用中详细解析。
二、如何实现柯里化
// 实现柯里化
function add(a, b, c, d){
return a + b + c + d;
}
// add函数柯里化的真正需求应该是下面这样:
var newAdd = Curry(add);
newAdd(1,2,3,4);
newAdd(1)(2)(3)(4);
newAdd(1,2)(3,4);
newAdd(1,2)(3)(4);
newAdd(1,2,3)(4);
newAdd(1)(2)(3,4);
newAdd(1)(2,3,4);
// 也就是说真正的Curry可以实现以上任意的执行组合 function Curry(fn,length){
var length = length || fn.length;
return function(){
if(arguments.length < length){
var combined = [fn].concat(Array.prototype.slice.call(arguments,0));
return Curry(FixedParmasCurry.apply(this,combined),length - arguments.length);
}else{
return fn.apply(this,arguments);
}
}
} function FixedParmasCurry(fn){
var _arg = Array.prototype.slice.call(arguments,1); //获取初始柯里化时传入的参数
return function(){
var newArg = _arg.concat(Array.prototype.slice.call(arguments,0)); //拼接当前执行的参数
return fn.apply(this, newArg);
}
}
实现分析:FixedParmasCurry(fn)本质上就是将已传入的参数作函数执行必要的参数直接执行,缺少对参数长度的判断。实现函数柯里化时初始化了必要参数的总长度length;然后每次计算还需要传入函数的长度,直到传入的参数arguments.length的长度大于或者等于需要的参数长度,就可以真正的执行函数了(23行)。
三、柯里化应用
例如下面这个模拟的ajax请求需求:
function ajax(type,url,data){
var xhr = new XMLHTTPRequest();
xhr.open(type,url,true);
xhr.send(data);
}
//如果有需求是将同一个参数同时发送给三个连接,下面这种做法明显的出现了代码冗余
ajax('POST','www.test.com','name=keyin');
ajax('POST','www.test2.com','name=keyin');
ajax('POST','www.test3.com','name=keyin');
//Curry
var ajaxCurry = curry(ajax);
var post = ajaxCurry("POST");
post('www.test.com','name=keyin');
post('www.test.com2','name=keyin');
post('www.test.com3','name=keyin');
可能在示例中还不那么明显,至少可以想象一件事情,当多个业务功能有一部分基础实现是一致的,如果通过像示例这样的共用一个参数导入,除了减低代码的耦合度,还可以灵活的拆解合并功能需求。
JavaScript函数式编程——柯里化的更多相关文章
- 【译】理解JavaScript中的柯里化
译文开始 函数式编程是一种编程风格,这种编程风格就是试图将传递函数作为参数(即将作为回调函数)和返回一个函数,但没有函数副作用(函数副作用即会改变程序的状态). 有很多语言采用这种编程风格,其中包括J ...
- javascript之反柯里化(uncurrying)
在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点.可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原 ...
- 简单粗暴详细讲解javascript实现函数柯里化与反柯里化
函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感:下面来一起看看究竟什么是函数柯里化: 维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第 ...
- javascript中利用柯里化函数实现bind方法
柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预 ...
- 浅谈JavaScript中的柯里化函数
首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...
- JavaScript函数的柯里化(currying)
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/currying.html 什么是js函数的currying /柯里化? 说到js的柯里化,相信很多朋友都会头大.或 ...
- JavaScript之函数柯里化
什么是柯里化(currying)? 维基百科中的解释是:柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术.意思就是当函 ...
- 简单粗暴详细讲解javascript实现函数柯里化
函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感:下面来一起看看究竟什么是函数柯里化: 维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第 ...
- JavaScript中的柯里化
转载自:https://www.cnblogs.com/zztt/p/4142891.html 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Ha ...
随机推荐
- 图解Python 【第七篇】:网络编程Socket
本节内容一览图: 前言总结: Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它 ...
- ScreenShot 截图工具类
import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Rect; import an ...
- Hander创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能.Android消息机制中引入了消息池.Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池 ...
- C#可以直接调用的Win32API
以前整理的Win32 API,可以直接在C#中直接调用,在做WinForm时还是很有帮助的.以前用在一个多窗口界面中,当轮询窗口时,调用API会提高很多效率. 源码下载 http://files.cn ...
- java配置SSM框架下的redis缓存
pom.xml引入依赖包 <!--jedis.jar --> <dependency> <groupId>redis.clients</groupId> ...
- Oracle数据库导入(expdp)和导出(impdp)
文档最后,列出了常用的一些导入导出的场景,以及一些导入导出的属性说明. 一.数据库导出(expdp) 使用sys或system账号登录oracle 通过"Window + R" 打 ...
- 在DELPHI中动态创建控件以及控件的事件
在DELPHI中我们经常要动态的创建控件以及控件的事件.例如,我们可能想根据程序需要动态的创建一些Tshape组件来创建某个图形,并使得在鼠标移动上去之后可以完成某些操作.这一般需要需要三步: 生成一 ...
- View的介绍和运用 && FlexBox布局
开始我们今天的项目学习啦~~~~~~ 1> 第一步当然是创建项目啦: 进入终端: 创建ViewDemo项目 命令如下啦,你看懂了对吧...嘻嘻!!! 2>View的介绍和运用 项目安装创建 ...
- SpringBoot: 4.SpringBoot整合listener(转)
整合方式一:通过注解扫描完成 Listener 组件的注册 1.编写listener package com.bjsxt.listener; import javax.servlet.ServletC ...
- Asp.net Core深入一:数据库访问(Mysql为例)
一.数据库概述 1.一个DBContext操纵一个数据库 2.DbContext下的一个DbSet<Model类>关联一个表,但是也可以只写一个表,DbContext可以关联其他的表. 3 ...