2018.10.22 星期一
颗粒化
柯里化(英语:Currying),又称为部分求值,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回一个新的函数的技术,新函数接受余下参数并返回运算结果。1
2
3
4
5
6
7
8
9
10var currying = function (fn) {
var _args = [];
return function () {
if (arguments.length === 0) {
return fn.apply(this, _args);
}
Array.prototype.push.apply(_args, [].slice.call(arguments));
return arguments.callee;
}
};
1 提高适用性。
1 | function square(i) {return i * i;} |
$PS: 利用闭包,绑定
2 延迟执行
柯里化的另一个应用场景是延迟执行。不断的柯里化,累积传入的参数,最后执行。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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118// # 0 简单:只能两个括号 $PS: 其实和第一条一样,利用闭包
var add = function(x) {
return function(y) {
return x + y;
};
};
console.log(add(1)(1)); // 输出2
var add1 = add(1);
console.log(add1(1)); // 输出2
var add10 = add(10);
console.log(add10(1)); // 输出11
// # 1 每次都是新结果,可以混合传参
// ## 1 直接定义 \#1
var add = function() {
var _args = arguments;
return function() {
if (!arguments.length) {
var sum = 0;
for (var i = 0,c; c = _args[i++];) {
sum += c
}
return sum
} else {
Array.prototype.push.apply(_args, arguments)
return arguments.callee
}
}
}
add(1)(2)(3)(4)();//10
add(5,3,9)(4)() // 21 // 正确
// ## 2 利用toString #3
function add() {
var _args = [].slice.call(arguments);
var adder = function () {
var _adder = function() {
[].push.apply(_args, [].slice.call(arguments));
return _adder;
};
_adder.toString = function () {
return _args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}
return adder.apply(null, [].slice.call(arguments));
}
// 输出结果,可自由组合的参数
console.log(add(1, 2, 3, 4, 5)); //f 15
console.log(add(1, 2, 3, 4)(5)); // f 15
console.log(add(1)(2)(3)(4)(5)); // f 15
console.log(add(1)(2,3)(3,5).toString()) // 14
alert(add(1,2)(3)) // alert: 6 true
/*
1)当使用console.log,或者进行运算时,隐式转换就会发生。
2) 当我们没有重新定义toString与valueOf时,函数的隐式转换会调用默认的toString方法,它会将函数的定义内容作为字符串返回。而当我们主动定义了toString/vauleOf方法时,那么隐式转换的返回结果则由我们自己控制了。
3) 其中valueOf的优先级会toString高一点。 */
// # 2 原来基础上增加
// ## 2.1_加法 不可以混合,只有第一个参数有意义
function add(n){//n
return function(m){
n+=m;
arguments.callee.toString=function(){
return n;
}
return arguments.callee;//引用当前正在调用的函数本身
}
}
//alert(add(1)(2)(3)/*.toString()*/);
//alert(add(1)(2)(3)(4)/*.toString()*/);
// ## 2.1_乘法 不可以混合,只有第一个参数有意义
function fn(n){
var count=n;
var tem=function(m){
count=count*m;
return tem;
}
tem.toString=function(){
return count;
}
return tem;
}
console.log(fn(2)(3)(4)) // f 22*3*4
console.log(fn(2,3)(3,4)(5,3)) // f 30=2*3*5
console.log(fn(2,3)(3,4)(5,3).toString) // 30
// ## 2.2 通用写法 \#1 \#2 可以混合传参
var curring = function(fn){
var _args = [];
return function cb(){
// return function () { // \#4
if(arguments.length === 0) {
return fn.apply(this, _args);
}
Array.prototype.push.apply(_args, [].slice.call(arguments));
return cb; //
// return arguments.callee; // \#4
}
}
var multi = function(){ // \#2
var total = 0;
var argsArray = Array.prototype.slice.call(arguments);
argsArray.forEach(function(item){
total += item;
})
/* \#4
for (var i = 0, c; c = arguments[i++];) {
total += c;
} */
return total
};
var calc = curring(multi);
calc(1,2)(3)(4,5,6);
console.log(calc()); // 21 //空白调用时才真正计算
calc(1,2)(3)()// 27 // 是在原来(21)的基础上增加的
3 固定易变因素。
1 | Function.prototype.bind = function(context) { |
函数记忆
1 | var isPrime1=(function(){ |
17:00