Skip to content

Commit 3af3eeb

Browse files
committed
函数柯里化
1 parent c9d0b29 commit 3af3eeb

3 files changed

Lines changed: 101 additions & 7 deletions

File tree

JS高级技巧/高级函数.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,66 @@ ECMAScript 5 为所有函数定义了一个原生的 bind() 方法,进一步
399399

400400
只要是将某个函数指针以值的形式进行传递,同时该函数必须在特定环境中执行,被绑定函数的效用就突显出来了。它们主要用于**事件处理程序以及 setTimeout() 和 setInterval() **。然而,被绑定函数与普通函数相比有更多的开销,它们需要更多内存,同时也因为多重函数调用稍微慢一点,所以最好只在必要时使用。
401401

402+
# 函数柯里化
403+
404+
与函数绑定紧密相关的主题是函数柯里化(function currying),它用于创建已经设置好了一个或多个参数的函数。函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数
405+
406+
function add(arg1,arg2){
407+
return arg1+arg2;
408+
}
409+
410+
function curriesAdd(num2){
411+
return add(5,num2);
412+
}
413+
console.log(add(2,3));//5
414+
console.log(curriesAdd(5));//10
415+
416+
这段代码定义了两个函数: add() 和 curriedAdd() 。后者本质上是在任何情况下第一个参数为 5的 add() 版本。尽管从技术上来说 curriedAdd() 并非柯里化的函数,但它很好地展示了其概念
417+
418+
**柯里化函数通常由以下步骤动态创建:调用另一个函数并为它传入要柯里化的函数和必要参数**。下面是创建柯里化函数的通用方式。
419+
420+
function curry(fn){
421+
var args=Array.prototype.slice.call(arguments,1);
422+
return function (){
423+
var innerArgs=Array.prototype.slice.call(arguments);
424+
var finnalArgs=args.concat(innerArgs);
425+
console.log("args->"+args+" innerArgs->"+innerArgs+" finnalArgs->"+finnalArgs);
426+
return fn.apply(null,finnalArgs);
427+
}
428+
}
429+
430+
function add(arg1,arg2){
431+
return arg1+arg2;
432+
}
433+
434+
var curriedAdd = curry(add, 5);
435+
console.log(curriedAdd(3)); //当调用 curriedAdd() 并传入3时,3会成为add()的第二个参数,同时第一个参数依然是5,最后结果便是和8。
436+
437+
也可以第一次直接把2个参数传进去;
438+
439+
var curriedAdd = curry(add, 5, 12);
440+
console.log(curriedAdd()); //17 在这里,柯里化的 add() 函数两个参数都提供了,所以以后就无需再传递它们了。
441+
442+
函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的 bind() 函数。
443+
444+
//这里是绑定函数的代码;
445+
var handler = {
446+
message: "Event handled",
447+
handleClick: function(name, event){
448+
console.log(this.message + ":"+ name + ":"+ event.type);
449+
}
450+
};
451+
function bind(fn,context){
452+
var args=Array.prototype.slice.call(arguments,2);
453+
return function (){
454+
var innerArgs=Array.prototype.slice.call(arguments);
455+
var finnalArgs=args.concat(innerArgs);
456+
console.log("args->"+args+" innerArgs->"+innerArgs+" finnalArgs->"+finnalArgs);
457+
return fn.apply(context,finnalArgs);
458+
}
459+
}
460+
461+
var oBtn=document.getElementById("btn");
462+
EventUtil.addHandler(oBtn,"click",bind(handler.handleClick, handler, "btn"));
463+
464+
JavaScript 中的柯里化函数和绑定函数提供了强大的动态函数创建功能。使用 bind() 还是 curry()要根据是否需要 object 对象响应来决定。它们都能用于创建复杂的算法和功能,当然两者都不应滥用,因为每个函数都会带来额外的开销。

index.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
//function curry(fn){
3+
function bind(fn,context){
4+
//var args=Array.prototype.slice.call(arguments,1);
5+
var args=Array.prototype.slice.call(arguments,2);
6+
return function (){
7+
var innerArgs=Array.prototype.slice.call(arguments);
8+
var finnalArgs=args.concat(innerArgs);
9+
console.log("args->"+args+" innerArgs->"+innerArgs+" finnalArgs->"+finnalArgs);
10+
//return fn.apply(null,finnalArgs);
11+
return fn.apply(context,finnalArgs);
12+
}
13+
}
14+
15+
var handler = {
16+
message: "Event handled",
17+
handleClick: function(name, event){
18+
alert(this.message + ":"+ name + ":"+ event.type);
19+
}
20+
};
21+
var btn = document.getElementById("my-btn");
22+
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));*/

test-file.html

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
</head>
77
<body>
88
<a href="javascript:;" id="btn">00000000000</a>
9+
<script src="index.js"></script>
910
<script>
1011
//这里是事件工具库;
1112
var EventUtil = {
@@ -62,16 +63,24 @@
6263
};
6364

6465
//这里是绑定函数的代码;
65-
var handler={
66-
message:"Event handler",
67-
handleClick:function(e){
68-
console.log(this.message+":"+ e.type);
66+
var handler = {
67+
message: "Event handled",
68+
handleClick: function(name, event){
69+
console.log(this.message + ":"+ name + ":"+ event.type);
6970
}
7071
};
72+
function bind(fn,context){
73+
var args=Array.prototype.slice.call(arguments,2);
74+
return function (){
75+
var innerArgs=Array.prototype.slice.call(arguments);
76+
var finnalArgs=args.concat(innerArgs);
77+
console.log("args->"+args+" innerArgs->"+innerArgs+" finnalArgs->"+finnalArgs);
78+
return fn.apply(context,finnalArgs);
79+
}
80+
}
81+
7182
var oBtn=document.getElementById("btn");
72-
oBtn.message="这是ID为btn的message属性";
73-
// EventUtil.addHandler(oBtn,"click",bind(handler.handleClick,handler));
74-
EventUtil.addHandler(oBtn,"click",handler.handleClick.bind(handler));//原生的bind方法;
83+
EventUtil.addHandler(oBtn,"click",bind(handler.handleClick, handler, "btn"));
7584

7685
</script>
7786
</body>

0 commit comments

Comments
 (0)