博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 专题之偏函数
阅读量:6995 次
发布时间:2019-06-27

本文共 2367 字,大约阅读时间需要 7 分钟。

JavaScript 专题系列第十四篇,讲解偏函数以及如何实现一个 partial 函数

定义

维基百科中对偏函数 (Partial application) 的定义为:

In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.

翻译成中文:

在计算机科学中,局部应用是指固定一个函数的一些参数,然后产生另一个更小元的函数。

什么是元?元是指函数参数的个数,比如一个带有两个参数的函数被称为二元函数。

举个简单的例子:

function add(a, b) {    return a + b;}// 执行 add 函数,一次传入两个参数即可add(1, 2) // 3// 假设有一个 partial 函数可以做到局部应用var addOne = partial(add, 1);addOne(2) // 3复制代码

个人觉得翻译成“局部应用”或许更贴切些,以下全部使用“局部应用”。

柯里化与局部应用

如果看过上一篇文章,实际上你会发现这个例子和柯里化太像了,所以两者到底是有什么区别呢?

其实也很明显:

柯里化是将一个多参数函数转换成多个单参数函数,也就是将一个 n 元函数转换成 n 个一元函数。

局部应用则是固定一个函数的一个或者多个参数,也就是将一个 n 元函数转换成一个 n - x 元函数。

如果说两者有什么关系的话,引用 中的描述就是:

Curried functions are automatically partially applied.

partial

我们今天的目的是模仿 underscore 写一个 partial 函数,比起 curry 函数,这个显然简单了很多。

也许你在想我们可以直接使用 bind 呐,举个例子:

function add(a, b) {    return a + b;}var addOne = add.bind(null, 1);addOne(2) // 3复制代码

然而使用 bind 我们还是改变了 this 指向,我们要写一个不改变 this 指向的方法。

第一版

根据之前的表述,我们可以尝试着写出第一版:

// 第一版// 似曾相识的代码function partial(fn) {    var args = [].slice.call(arguments, 1);    return function() {        var newArgs = args.concat([].slice.call(arguments));        return fn.apply(this, newArgs);    };};复制代码

我们来写个 demo 验证下 this 的指向:

function add(a, b) {    return a + b + this.value;}// var addOne = add.bind(null, 1);var addOne = partial(add, 1);var value = 1;var obj = {    value: 2,    addOne: addOne}obj.addOne(2); // ???// 使用 bind 时,结果为 4// 使用 partial 时,结果为 5复制代码

第二版

然而正如 curry 函数可以使用占位符一样,我们希望 partial 函数也可以实现这个功能,我们再来写第二版:

// 第二版var _ = {};function partial(fn) {    var args = [].slice.call(arguments, 1);    return function() {        var position = 0, len = args.length;        for(var i = 0; i < len; i++) {            args[i] = args[i] === _ ? arguments[position++] : args[i]        }        while(position < arguments.length) args.push(argumetns[position++]);        return fn.apply(this, args);    };};复制代码

我们验证一下:

var subtract = function(a, b) { return b - a; };subFrom20 = partial(subtract, _, 20);subFrom20(5);复制代码

写在最后

值得注意的是:underscore 和 lodash 都提供了 partial 函数,但只有 lodash 提供了 curry 函数。

专题系列

JavaScript专题系列目录地址:。

JavaScript专题系列预计写二十篇左右,主要研究日常开发中一些功能点的实现,比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里、递归、乱序、排序等,特点是研(chao)究(xi) underscore 和 jQuery 的实现方式。

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

转载地址:http://pyzvl.baihongyu.com/

你可能感兴趣的文章
java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut
查看>>
[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链
查看>>
Oracle DBA手记4:数据安全警示录
查看>>
HDU 4638 Group(分组)
查看>>
BZOJ 1037 生日聚会Party(DP)
查看>>
DG - 将physical standby置于read-only模式
查看>>
nginx的反向代理proxy_pass指令
查看>>
IIs工作原理
查看>>
用NSData玩转二进制文件的读写
查看>>
用户 'NT AUTHORITY\NETWORK SERVICE' 登录失败。
查看>>
ZOJ 1871. Steps
查看>>
Win8使用技巧
查看>>
js+ajax获取文件大小
查看>>
Normalization VS Denormalization [转]
查看>>
perl 实现ascall 码转换
查看>>
KVO 进阶
查看>>
【转】plist文件的内容清空
查看>>
mysql数据库全备和全备还原(使用Xtrabackup)
查看>>
VS无法启动调试:“生成下面的模块时,启用了优化或没有调试信息“
查看>>
C#直接读取磁盘文件(类似linux的Direct IO模式)
查看>>