js高阶函数
一、高阶函数
高阶函数是对其他函数进行操作的函数,可以将它们作为参数或通过返回它们。简单来说,高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回
-
是函数
-
可以作为返回值
-
可以作为参数
1、作为参数传递
js函数可以传入变量,而函数也是一个变量,自然也可以传递
function add (x, y, f) { return f(x) + f(y) } let num = add(2, -2, function (a){return a }) console.log(num) // 0
2、作为返回值
函数柯里化
let demo = function (x) { return function (y) { return x + y } }; console.log(demo(3)) // Function(y){return 3 + y} console.log(demo(3)(4)) // 7
这边只能够固定的两个参数,以下是通用的柯里化函数
方式一:
思路:
-
获取传入的函数, 函数的形参数,返回的函数
-
获取每次调用返回函数时的实参
-
实参等于形参时,执行传入函数,否则,继续返回函数
// 通用柯里化函数 const curry = (fn, ...arg) => { let all = arg || []; // 调用时的实参 let length = fn.length; // 定义函数时形参个数 return (...rest) => { let _args = all.slice(0); // 获取之前传入的实参,和当前调用时传入的参数合并 _args.push(...rest); if (_args.length < length) { // 如果实参数小于形参数, 继续返回函数 return curry.call(this, fn, ..._args); } else { // 如果实参数等于形参数,调用这个传递来的 函数 return fn.apply(this, _args) } } } const add = curry((a,b) => a+b) const item = add(1); console.log(item(2)); // 3
方式二:
思路:不获取形参数量,直接获取实参,然后传递,如果形参大于实参,返回的是一个函数,如果形参等于了实参,就执行函数
var curry1 = function(func){ var args = [].slice.call(arguments,1); // 首先我们对通用函数截取参数 return function(){ var newArgs = args.concat([].slice.call(arguments)); //将每次添加的函数连接起来 return func.apply(this,newArgs); //将此函数的数组赋给目标函数 并传入参数 } } function sub(a,b){ return a-b; } var subcurry = curry1(sub,5); console.log(subcurry(3)); // 2
3、利用高阶函数实现filter/map/forEach/every/some
3.1.filter
过滤, 返回符合条件的元素
// 高阶函数实现filter Array.prototype.myFilter = function (fn) { let arr = []; for(let i = 0; i < this.length; i++) { // this指向的是Array实例 let item = this[i] if (fn(item, i, this)) { arr.push(item) } } return arr } var arr = [1,2,3,4,5]; console.log(arr.myFilter((item, i, arr) => { return item > 2; })) // [3,4,5 ]
3.2.map
返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
// Map Array.prototype.myMap = function (fn) { let arr = [] for(let i = 0; i < this.length; i++) { let item = fn(this[i], i, this) // 调用该函数 arr.push(item) } return arr } var arr = [1,2,3,4]; console.log(arr.myMap((item, i, arr) => { return item*2; })) // [2,4,6, 8]
3.3 forEach
遍历数组、
// forEach() Array.prototype.myForEach = function (fn) { for(let i = 0; i < this.length; i++ ) { fn(this[i], i, this) } } var arr = [1,2,3,4] arr.myForEach((item, i, arr) => { console.log(item) // 1,2,3,4 })
3.4. every
检测数组所有元素是否都符合指定条件
Array.prototype.myEvery = function(fn,value){ var arr = this; for (var i = 0; i < arr.length; i++) { var result = fn.call(value, arr[i], i, arr); if (!result) return false; } return true; } var arr = [1,2,3,4] console.log(arr.myEvery((item, i, arr) => { return item > 0 // true }))
3.5.some
数组中有一个符合条件,就返回true
Array.prototype.mySome = function(fn, value){ var arr = this; for (var i = 0; i < arr.length; i++) { var result = fn.call(value, arr[i], i, arr); if (result) return true; } return false; } var arr = [1,2,3,4] console.log(arr.mySome((item, i, arr) => { return item < 0 // false }))