高阶函数

1. 高阶函数

定义:

高阶函数至少满足下列一个条件

  1. 接受一个或多个函数作为输入
  2. 返回一个函数
  • 常见的高阶函数
1
2
// Array.prototype.map 接受一个函数作为参数。
const newArr = arr.map((item,index)=>item+index));

2. 函数组合

定义:

将多个函数组合生成一个新函数的过程

1
2
3
4
5
function compose(g, f) {
return function (x) {
return g(f(x));
};
}

应用场景

  1. eg: 对输入进行多次格式化或者变形,得到一个新的输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 返回string小写
function lowerCase(input) {
return input && typeof input === "string" ? input.toLowerCase() : input;
}

// 返回string大写
function upperCase(input) {
return input && typeof input === "string" ? input.toUpperCase() : input;
}

// 去掉前后空格
function trim(input) {
return typeof input === "string" ? input.trim() : input;
}

// 变为数组
function split(input, delimiter = ",") {
return typeof input === "string" ? input.split(delimiter) : input;
}

const beforeParams = " a,b,c,D ";
const formatParams = compose(split(trim(lowerCase(beforeParams))));

// ['a','b','c','d']

compose的实现

1
2
3
4
5
function compose(...funcs) {
return function (x) {
return funcs.reduce((arg, fn) => fn(arg), x);
};
}

3. 函数柯里化

定义

在数学和计算机中,柯里化是一种将使用多个参数的一个函数转化成一系列使用一个参数的函数的技术。

一个函数(多个参数)—> 一个函数(一个参数)

1
2
3
4
5
6
7
8
const abc = function (a, b, c) {
return [a, b, c];
};

const curried = curry(abc);
curried(a)(b)(c); // [a,b,c];
curried(a, b)(c); // [a,b,c];
curried(a, b, c); // [a,b,c];

从上面的例子可以看出,curried这个函数,可能会返回一个函数,可能返回一个结果。

实现

1
2
3
4
5
6
7
8
9
10
11
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}

4. 偏函数

定义

偏函数是指,固定一个函数的某些参数,返回一个更小元的函数。元的意思就是参数,如一个参数的函数也叫一元函数。

1
2
3
4
5
6
7
8
9
10
11
function buildUri(scheme, domain, path) {
return `${scheme}://${domain}/${path}`;
}

const myGithubPath = _.partial(buildUri, "https", "github.com");

// https://github.com/semlinker/semlinke
const profilePath = myGithubPath("semlinker/semlinker");

// https://github.com/semlinker/awesome-typescript
const awesomeTsPath = myGithubPath("semlinker/awesome-typescript");

实现

1
2
3
4
5
6
7
function partial(fn){
const args = [].slice.call(arguments,1);
return newFunc(){
const newArgs = args.concat([].slice.call(arguments));
return fn.apply(this, newArgs);
}
}

偏函数与柯里化的区别

  • 偏函数应用是固定一个函数的一个或者多个参数,并返回一个可以接收剩余参数的函数。
  • 柯里化将函数转化为多个嵌套的一元函数,也就是每个函数只接受一个参数。

5. 惰性函数

定义

惰性函数是指,当第一次根据条件执行函数后,在第 2 次调用函数时,就不再检测条件,直接执行函数。

例子

  1. 原始写法。
1
2
3
4
5
6
7
8
9
function addHandler(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false)
}else if(element.addEvent){
element.attachEvent('on'+type,handler);
}else{
element.
}
}
  1. 惰性函数写法 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function addHandler(element, type, handler) {
if (element.addEventListener) {
addHandler = (element, type, handler) => {
element.addEventListener(type, handler, false);
};
} else if (element.attachEvent) {
addHandler = (element, type, handler) => {
element.attachEvent("on" + type, handler);
};
} else {
addHandler = (element, type, handler) => {
element["on" + type] = handler;
};
}

return addHandler(element, type, handler);
}
  1. 惰性函数写法 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const addHandler = (function () {
if (element.addEventListener) {
return (element, type, handler) => {
element.addEventListener(type, handler, false);
};
}

if (element.attachEvent) {
return (element, type, handler) => {
element.attachEvent("on" + type, handler);
};
}

return (element, type, handler) => {
element["on" + type] = handler;
};
})();

6. 缓存函数

缓存函数将函数的计结果存储起来,当下次以同样参数调用该函数时,直接返回已缓存的结果,无需再次执行函数。这是常见的一种空间换时间的优化方式。

1
2
3
4
5
6
7
function memorized = (fn){
const cache = Object.create(null);
return function (...args){
const _args = JSON.stringify(args);
return cache[_args] || (cache[_args] = fn.apply(fn, args))
}
}
-------------本文结束感谢您的阅读-------------