简要描述:
- 介绍JavaScript中的高阶函数,在 JavaScript 中,函数是一种特殊类型的对象,它们是 Function objects。将通过高阶函数的定义来展开介绍及实际中的应用
高阶函数英文叫Higher-order function。那么什么是高阶函数?
在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
- 接受一个或多个函数作为输入
- 输出一个函数
高阶函数可以理解为输入一个函数,输出一个函数。在JS编程的时候很多时候都用过,比如Array的reduce,sort,map等方法,他们就是高阶函数。
取个简单的例子解释还原一下高阶函数
let add = function(p1){
this.value = function (p2) {
return p1+p2
}
return this.value
}
// let result = add(1)(2)
// console.log(result)
// print 3
上面这段代码的执行方式是add(1)(2),结果返回3,
这个函数的执行看起来平时的不太一样,它可以看做分解为第一次执行返回了一个函数,第二次执行才返回结果。如果我们需要连续三次相加的话,那么上面的代码就需要改写成
let add = function(p1){
this.value = function (p2) {
return (p3) => p1+p2+p3
}
return this.value
}
// let result = add(1)(2)(3)
// console.log(result)
// print 6
从上面的例子可以看出我们需要进行重复的操作越多,上面需要返回的函数的次数越多,由此可见高阶函数引入和使用的场景一般是出现重复或者相似的代码。
let add = function(a,b){
return a + b;
};
function math(func,array){
return func(array[0],array[1]);
}
// console.log(math(add,[1,2]));
// 3
这段代码片段是不是有点熟悉,有点像apply,call的使用。
之前在了解高阶函数的时候,写过一个关于无限相加的高阶函数方法,算是上面函数的升级版
function constructor () {
this.add =function(arr){
var sumval = 0
if (arr.constructor !== Array){
arr = [...arr]
}
arr.forEach(val=>{
sumval+=val
})
return sumval
}
sumvalue = sum.sumvalue
sumvalue=sumvalue+this.add(arguments)
console.log(sumvalue)
sum.sumvalue= sumvalue
var callback = function(){
return constructor(...arguments)
}
callback.value=function(){
return sum.sumvalue
}
return callback
}
function sum(){
//if(sum.construct!== undefined){
// return sum.construct
//}
that = sum
that.sumvalue = 0
that.value=function(){
return that.sumvalue
}
sum.construct = new constructor(...arguments)
return sum.construct
}
export default sum
调用的方式sum(1,2)(2,31,123)(1).value(),最后通过调value函数获取保存的结果。
在JavaScript中,函数是第一类对象,其既可以作为参数传递,也可以作为其他函数的返回值输出。由于高阶函数的返回值是一个函数,所以高阶函数还可作为一种模式的构造器,比如有若干排序算法(快排,冒泡,希尔等),就可以生成一个排序器。
//排序器
var sortGenerator = function(sortFunc){
return function(args){
var arguments = [].slice.call(args);
return sortFunc(arguments);
}};
//引入快速排序算法
var quickSort = require('quickSort.js');
var quickSorter = sortingGenerator(quickSort);
//应用算法
quickSorter (4, 22, 44, 66, 77);
说到高阶函数不得不说一下偏函数和函数的柯里化与反柯里化,
-
偏函数,偏函数就是假设有一个参数或变量已经预置的函数A,我们通过调用A来产生一个新的函数B,函数B就是我们说的偏函数。
-
柯里化,俗称“部分求值”。一个柯里化函数首先是会接受一些参数,但是接受这些参数之后,该函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。
-
反柯里化,它所做的就是把已经内置的特定使用场景的函数通过参数解放出来,提高函数的适用范围。
// 函数封装后
function check(reg, txt) {
return reg.test(txt)
}
check(/\d+/g, 'test') //false
check(/[a-z]+/g, 'test') //true
// Currying后
function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1') // true
hasNumber('testtest') // false
hasLetter('21212')
// bind的实现机制
Function.prototype.bind = function (context) {
var _this = this
var args = Array.prototype.slice.call(arguments, 1)
return function() {
return _this.apply(context, args)
}
}
从上面可以看出柯里化的优点,就是柯里化之后,
- 参数变得可复用了;
- 同时前置条件变成了可确认状态,比如ajax里的post和get方法就是如此,省去一个参数type的传入,避免了一个逻辑的判断;
- 运行的延迟,可以看做不断的柯里化,累积传入的参数,最后执行。
反柯里化的优点简单介绍一下就是扩展函数的使用场景,适配更多条件。
备注
- 暂无