Fork me on GitHub

惰性函数与函数柯里化

惰性函数与函数柯里化

惰性函数

就我自己对其的理解来说,惰性函数表示函数执行的分支只会在函数第一次掉用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。

来一个例子了解下。在我们平时耍ajax时候,需要不断新建xhr对象,这时候就可以考虑使用惰性函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let createXHR = () => {
let xhr = null;
if(typeof XMLHttpRequest !== 'undefined') {
xhr = new XMLHttpRequest();
createXHR = () => { //覆盖原有函数
return new XMLHttpRequest();
}
} else {
try {
//假设进行浏览器对应xhr对象查找
} catch(e) {
//假设进行浏览器对应xhr对象查找
}
}
return xhr;
}

第一次执行函数会先各种查找对应浏览器支持的xhr然后返回该xhr,后面执行函数都直接返回一个新的浏览器对应支持的xhr对象,就不必每次都去根据浏览器判断xhr对象。

另一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
let addEvent = function(type, el, fn) {
if(window.addEventListener) {
el.addEventListener(type, fn, false);
addEvent = function(type, el, fn) {
el.addEventListener(type, fn, false);
}
} else if(window.attachEvent) {
el.attachEvent('on' + type, fn);
addEvent = function(type, el, fn) {
el.attachEvent('on' + type, fn);
}
}
}

我们每当使用一次 addEvent 函数时都会进行一次判断。惰性函数帮我们解决这个问题。

函数柯里化

维基百科上这样定义函数柯里化

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

此处列出两种curry函数实现方式:

实现一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let curry = function(fn) => {
let args = [].slice.call(arguments, 1);
return function() {
let innerArgs = [].slice.call(arguments);
let finalArgs = innerArgs.concat(args);
return fn.apply(this, finalArgs);
}
}
let add = (a, b, c) => {
return a + b + c;
}
let s1 = sub_curry(add, 10)(1, 2);
let s2 = sub_curry(add)(1, 2, 10);
let s3 = sub_curry(add, 10, 1)(2);
console.log(s1);
console.log(s2);
console.log(s3);

实现二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let curry = function(fn, args) {
let length = fn.length; //length即为函数形参的个数
args = args || [];

return function() {
let _args = args.slice(0);
let arg, i;
for(i = 0; i < arguments.length; i++) {
arg = arguments[i];
_args.push(arg);
}
if(_args.length < length) {
return curry.call(this, fn, _args);
} else {
return fn.apply(this, _args);
}
}
}
let con = function(a, b, c) {
console.log([a, b, c]);
}
let s = curry(con);
s(1, 2, 3);
s(1, 2)(3);
s(1)(2)(3);

柯里化可是将一个多参数的函数转换成多个单参数的函数,但是现在我们不仅可以传入一个参数,还可以一次传入两个参数,甚至更多参数.