从bind函数看js中的柯里化
以下是百度百科对柯里化函数的解释:柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。概念太抽象,可能并不怎么好理解,下面来举个栗子说明什么是函数柯里化。
1 var obj = { 2 name: "aaaaaaaaaa" 3 }; 4 5 var name = "bbb"; 6 7 function fn(n1, n2) { 8 console.log(this.name); 9 console.log(n1 + n2); 10 } 11 12 setTimeout(fn.bind(obj, 1, 2), 2000);
我们都知道bind函数作用与call和apply作用相似,但是与他们不同的是,bind函数不立即执行,而是简单的对函数做了一个预处理(加工)。等待调用的时候才执行。
但是这个函数方法并不兼容IE6-8,接下来我们自己实现一个myBind函数,功能类似bind
function myBind(fn, context) { var outerArg = Array.prototype.slice.call(arguments, 2); console.log(outerArg) return function() { fn.apply(context, outerArg); } } setTimeout(myBind(fn, obj, 1, 2), 2000);
主要实现思路是:首先把改变函数执行的上下文,这个我们用apply,因为后面如果要传参数,需要先截取数组,排除非参数项,得到是数组,所以就要用apply传参,call和apply的区别在这时就很明显。可以看到我们在函数中又返回了函数,如果不这样做,函数就会立即执行,那定时器就失去了意义。实际上这就体现了柯里化函数。对传入的参数做了预处理,然后再返回函数,函数调用时执行返回的函数。
接下来,我们把这个方法添加到函数对象的原型上。这里还需要改动一下,把其中的this指向改动一下。
1 var obj = { 2 name: "aaaaaaaaaa" 3 }; 4 5 var name = "bbb"; 6 7 Function.prototype.myBind = function myBind(context) { 8 var _this=this; 9 var outerArg = Array.prototype.slice.call(arguments, 1); 10 return function() { 11 12 _this.apply(context, outerArg); 13 } 14 } 15 16 function fn(n1, n2) { 17 console.log(this.name); 18 console.log(n1 + n2); 19 } 20 21 setTimeout(fn.myBind(obj, 1, 2), 2000);
到这里,你对函数柯里化的应该有了基本认识,有关函数柯里化还有更多博大精深的地方,不过你可以看到,其原理都是由基本的js知识构成的,然后通过这些基础知识才构思出来的,所以打好基础很重要。