偏函数、高阶函数、柯里化、匿名函数

好久没写博客,从一道题目开始吧

实现一个sum函数,支持sum(1,2)和sum(1)(2)两种调用方式

说实在的,没啥难的,很简单写出来

function sum(a, b) { if (b) { return a + b; } return (b) => a+b; }

或者用ES6的展开操作符,或者是arguments

function sum(...args) { if (args.length === 2) { return args[0] + args[1]; } if (args.length === 1) { return (b) => b + args[0] } }

考察的内容其实就是函数作为返回值,简单涉及到了闭包,还有arguments的判断,ES6展开操作符的剩余语法。然后可以继续发散,ES6熟不熟啊,闭包理解到不到位啊,arguments是不是数组,怎么转成数组……

不写了,不写了,展开能问的太多了。今天主要的目的是写一写函数相关,解释一下那些常见的概念:偏函数、高阶函数、柯里化、匿名函数。

偏函数

偏函数(Partial application),wiki上解释

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

大概意思,偏函数会固定一些参数,产生更少参数的函数。

改一下上面的题目:

实现一个sum函数,可以支持固定一个参数的的调用方式;如

var sum1 = sum(1);

sum1(2) // 3

function sum(base) { return (num) => base + num; } var sum1 = sum(1);

或者使用bind

function sum(a, b) { return a + b; } var sum1 = sum.bind(null, 1);

这里可以引申出bind的用法,bind和call的区别,call和apply的区别。就不多赘述了。之前写过一篇博客bind、apply与call。

高阶函数

在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数: 接受一个或多个函数作为输入 输出一个函数

wiki链接。

可以这么理解,如果可以接受函数作为入参和出参的,可以认为支持高阶函数。JS中,函数是一等公民,各种高阶函数随处可见,很容易写一个例子:

const print = console.log; const foo = (a , b, printFn) => a + b; foo(1, 2, print);

说个题外话,有这样一道题目:

[1,2,3].map(parseInt)

我感觉这个题目有点考api记忆了,不过如果熟练的话也就还好。map是一个高阶函数,接受一个函数作为参数,他会给入参函数传入两个值,item和index。parseInt接受两个参数,数值和进制。也就是执行

parseInt(1, 0); parseInt(2, 1); parseInt(3, 2);

答案[1, NaN, NaN]我就不多说了。

柯里化

在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

wiki链接。

大概定义一下,可以认为curry之后的函数,可以接受一个参数,之后返回一个接受剩余参数的函数。

期望可以这么执行:

var add = curry((a, b) => a + b); add(1, 2); // 可以正常运行 var add1 = add(1); add1(2); // 也可以这么使用

可以发现,这不就是上面的题目吗?当然,稍有不同的地方在于,这里是通过curry把一个正常函数curry化。我们也来实现一个。

function curry (fn) { return (...args) => { if (args.length === fn.length) { return fn.apply(null, args); } return fn.bind(null, args[0]) } }

很明显,上面用到了偏函数的实现去做了curry,也可以不使用bind,在使用别的方法之前,加一些限定条件。

上面的curry简单处理了一个参数的情况,我们希望curry更智能一些,假设函数有10个参数,如果传了5个,又传了3个,又传了2个,只有最后一次才会返回结果。

// 为了使用递归,写了一个helper function helper (fn, ...args) { if (args.length === fn.length) { return fn.apply(null, args); } return (...argsMore) => createFn(fn, ...args, ...argsMore); } function curry (fn) { return (...args) => createFn(fn, ...args); }

多说一个概念,thunk,阮一峰老师在他的博客里介绍过Thunk 函数的含义和用法,大家可以看一下,其实也就是curry的一处用法。

匿名函数

在计算机编程中,匿名函数(英语:anonymous function)是指一类无需定义标识符(函数名)的函数或子程序,普遍存在于多种编程语言中。

wiki。

匿名函数相对命名函数而言,就是一些一次性使用的场景下,比如一些事件处理函数,可能只执行一次,可以使用匿名函数。

这个概念经常用,举个例子。

[1,2,3].map((item, index) => `item ${index}: ${item}`);

匿名函数的概念很简单,上面写的箭头函数容易考察一些this指向的问题。

比如为什么箭头函数不能使用new,怎么做到绑定this的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfggy.html