Js偏函数

更新日期: 2022-01-12 阅读: 1.4k 标签: 函数

定义

维基百科中对偏函数 (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

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

柯里化与局部应用

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

其实也很明显:

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

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

如果说两者有什么关系的话,引用 functional-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

然而使用 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(arguments[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 函数。

原文来自:https://github.com/mqyqingfeng/Blog/issues/43

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/11147

相关推荐

JavaScript push() 方法详解

push() 方法主要用于向数组的末尾添加一个或多个元素,其返回值为添加后新的长度,即push后的数组长度,该值为number类型。介绍:一个数组中添加新元素、把一个数组的值赋值到另一个数组上、在对象使用push

什么是纯函数_以及为什么要用纯函数?

当我第一次听到 “纯函数 (Pure Function)” 这个术语的时候我很疑惑。常规的函数做错了什么?为什么要变纯? 为什么我需要纯的函数?除非你已经知道什么是纯函数,否则你可能会问同样的疑惑

让我们来创建一个JavaScript Wait函数

Async/await以及它底层promises的应用正在猛烈地冲击着JS的世界。在大多数客户端和JS服务端平台的支持下,回调编程已经成为过去的事情。当然,基于回调的编程很丑陋的。

什么是函数的副作用——理解js编程中函数的副作用

函数副作用是指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。副作用的函数不仅仅只是返回了一个值,而且还做了其他的事情

js中sort函数用法总结_sort排序算法原理

js中sort方法用于对数组的元素进行排序,并返回数组。默认排序顺序是根据字符串Unicode码点。如果要得到自己想要的结果,不管是升序还是降序,就需要提供比较函数了。该函数比较两个值的大小,然后返回一个用于说明这两个值的相对顺序的数字

javascript封装函数

使用函数有两步:1、定义函数,又叫声明函数, 封装函数。2、调用函数var 变量 = 函数名(实参);对函数的参数和返回值的理解

js中reduce()方法

reduce() 方法接收一个函数作为累加器,reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(上一次回调的返回值),当前元素值,当前索引,原数组。

javascript回调函数的理解和使用方法(callback)

在js开发中,程序代码是从上而下一条线执行的,但有时候我们需要等待一个操作结束后,再进行下一步操作,这个时候就需要用到回调函数。 在js中,函数也是对象,确切地说:函数是用Function()构造函数创建的Function对象。

js调用函数的几种方法_ES5/ES6的函数调用方式

这篇文章主要介绍ES5中函数的4种调用,在ES5中函数内容的this指向和调用方法有关。以及ES6中函数的调用,使用箭头函数,其中箭头函数的this是和定义时有关和调用无关。

js构造函数

JS中的函数即可以是构造函数又可以当作普通函数来调用,当使用new来创建对象时,对应的函数就是构造函数,通过对象来调用时就是普通函数。在我们平时工作中,经常会需要我们创建一个对象,而我们更多的是使用对像直接量,直接创建

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!