javascript之偏函数

本文探讨了计算机科学中的局部应用概念,通过实例说明如何利用局部应用减少函数参数数量,并对比了局部应用与柯里化的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

维基百科中对偏函数(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函数
如果两者有什么关系的话,引用function-programming-jargon的描述是:

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

第一版

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


// 第一版
// 似曾相识的代码
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(arguments[position++]);
        return fn.apply(this, args);
    };
};

我们来验证一下

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

写在最后

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值