很久没写博客,从一道题目开始吧javascript
实现一个sum函数,支持sum(1,2)和sum(1)(2)两种调用方式html
说实在的,没啥难的,很简单写出来java
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是否是数组,怎么转成数组……api
不写了,不写了,展开能问的太多了。今天主要的目的是写一写函数相关,解释一下那些常见的概念:偏函数、高阶函数、柯里化、匿名函数。数组
偏函数(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.app
大概意思,偏函数会固定一些参数,产生更少参数的函数。编程语言
改一下上面的题目:函数
实现一个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。
在数学和计算机科学中,高阶函数是至少知足下列一个条件的函数: 接受一个或多个函数做为输入 输出一个函数
能够这么理解,若是能够接受函数做为入参和出参的,能够认为支持高阶函数。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),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数并且返回结果的新函数的技术。
大概定义一下,能够认为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的。
这个问题,我打算留到下一篇写。嘿嘿嘿😝
完。感谢阅读。