函数绑定和函数柯里化

函数绑定

函数绑定的定义
咱们直接来看例子吧

未绑定

未进行绑定时
      在上面这个例子中,创建了一个叫做 handler 的对象。handler.handleClick()方法被分配为
一个 DOM 按钮的事件处理程序。当按下该按钮时,就调用该函数,显示一个警告框。
虽然警告框应该显示 Event handled ,然而实际上显示的是 undefiend 。
这个问题就是没有保存 handler.handleClick()的环境,所以 this 对象最后是指向了 DOM 按钮而非 handler。
这就是绑定函数存在的意义,创建函数并保留代码的执行环境。

闭包

闭包
      解决方案有,在 onclick 事件处理程序内使用了一个闭包直接调用 handler.handleClick()。就这一个闭包还行,如果创建多个闭包可能会令代码变得不好理解和调试,万一哪出了个bug呢。所以,很多JavaScript 库实现了一个可以将函数绑定到指定环境的函数。这个函数一般都叫 bind()。

bind()方法的语法

       一个简单的 bind()函数接受一个函数和一个环境,并返回一个在给定环境中调用给定函数的函数, 并且将所有参数原封不动传递过去。语法如下:
bind()
      它看着简单,功能还是挺强大的。在 bind()中创建了一个闭包,闭包使用 apply()调用传入的函数,并给 apply()传递 context 对象和参数。这个 arguments 对象是内部函数的,而非 bind()的。

bind() 实现函数绑定

bind()实现绑定
      当调用返回的函数时,它会在给定环境中执行被传入的函数并给出所有参数。 就这个例子,bind()函数创建了一个保持了执行环境的函数,并将其传给btn.addEventListener()。DOM中addEventListener() 方法用于向指定元素添加事件句柄。这样按钮就能成功指向handler了。

原生bind方法

原生bind()方法
      handler.handleClick()方法和平时一样可以获得 里面 对象,因为所有的参数都通过被绑定的函数直接传给了它。也可以这样,你不用再自己定义 bind()函数了,而是可以直接在函数上调用这个方法。

拓展bind()语法

拓展
      如果不能确定bind()方法是否存在,那么可以使用以下方法来绑定函数。如果bind()方法存在,使用bind()方法绑定函数并则返回新函数(fn.bind(context))如果bind()方法不存在,这样实现将fn()绑定到对象context上。
      从以上可以看出,“fn.apply(context, argument)”的效果与“fn.bind( context )”的效果是一样的和原来执行的效果也相同,这样更加严谨些。
      只要是将某个函数指针以值的形式进行传递,同时该函数必须在特定环境中执行(比如例子中的handler.handleClick(),被绑定函数的效用就突显出来了。它们主要用于事件处理程序以及 setTimeout() 和 setInterval()。

函数柯里化

      函数柯里化的方法与函数绑定是一样的,唯一的区别在于 函数柯里化所创建的函数还需要传入一些参数。
      函数柯里化的用途是指定函数的不变参数,使得多次调用函数的时候不用重复传入相同的参数,就像Java里面的static变量。

由apply()方法实现柯里化

      动态创建柯里化函数:调用另一个函数并为它传入要柯里化的函数和必要的参数。
apply()实现柯里化
柯里化函数步骤:
第一步:柯里化函数,并返回一个新函数。var oldSum = curry(oldSum, 3)
1、args=[3],外部函数就是curry(),且将第二个参数"3"保留在了数组args中。我们知道arguments对象可以访问传入到函数中的多个实参,这里就“3”这个实参保留在了args数组中。
2、return function () {}返回匿名函数
第二步:调用newSum(4)
1、innerArgs=[4],这里将内部函数newSum的参数"4"保留在innerArgs中。
2、在外部、内部函数的参数数通过操作符concat拼接成一个数组并保留在finalArgs中。
3、fn.apply(null, finalArgs) ==> fn(finalArgs) ==> oldSum(3, 4)
最后得出结果为7

另外一些小知识:

prototype 属性使您有能力向对象添加属性和方法。
slice() 方法可从已有的数组中返回选定的元素。
concat() 方法用于连接两个或多个数组。
call() 方法是预定义的 JavaScript 方法。
它可以用来调用所有者对象作为参数的方法。
通过 call(),您能够使用属于另一个对象的方法。
call() 方法可接受参数。

两个外部函数参数

两个外部函数参数

解析:

      此时外部函数参数有两个分别为“4”和"6",通过新函数newSum()传入到原始函数oldSum()的实参有三个,但由于oldSum()只有两个形参,所以内部函数(也就是newSum)的实参被忽略,只传入给了原始函数“4”和“6”这两个参数。

由bind()方法实现柯里化

      bind()方法不仅仅可以将函数绑定到一个对象上,它还有其它的作用:
      除了第一个实参外,传入bind()方法的实参也会被绑定到this对象上,这里的this的值绑定到传入bind()方法的对象或函数上。
      bind()方法实现柯里化的方法就是:在this的值后面再传入另一个参数即可。
bind()实现函数柯里化

更多:

      传入bind()方法的实参优先绑定到绑定函数(相当于原始函数)的形参上。
      如果传入bind()方法的实参个数多于绑定函数的形参个数,一一对应,则忽略最后的几个实参;
      如果传入bind()方法的实参个数少于绑定函数形参的个数,则实参绑定到前几个形参,剩下的形参绑定新函数传入的实参,若此时新函数传入的实参多个剩下形参的个数,一一对应,则忽略新函数的最后几个实参。

最后,两者区别:

      柯里化就是在绑定函数的基础上,在this值之后再传入实参。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值