深入理解javascript之函数

函数的作用域和this的指向我已经在前面的文章中讲过,今天主要讲讲函数的绑定。函数绑定要创建一个函数,可以在特定的this环境中以指定参数调用另外一个函数。该技巧常常和回调函数与事件处理程序一起使用,以便在将函数作为变量传递的同时保留函数的代码执行环境。


函数绑定

看下面的例子:

var handler = {
  message:"消息来了!",
  handlerClick :function(event){
    document.write(this.message);
  }
}
//一般的指定不能改变this的指向
var btn = document.getElementById("btn");
btn.addEventListener("click",handler.handlerClick,false);
//返回undefined 因为this的范围指向的是btn而不是hanlder

结果返回的是undefined,因为this的指向是btn这个DOM对象而不是hanlder,所以根本找不到handler.message。

所幸的是,我们可以通过一个闭包来解决这个问题。

//可以通过一个闭包来解决这个问题
btn.addEventListener("click",function(event){
  handler.handlerClick(event);
},false);
//返回 消息来了!,解决问题

但是用闭包始终不是一个好办法,因为过多的闭包会使代码变得不易调试和理解,所以我们可以利用apply来调整this的指向。接下来我们定义一个bind方法。

//但是过多的使用闭包并不是一个好办法,所以我们使用apply来改变this的指向
function bind(fn,context){
  return function(){
    return fn.apply(context,arguments);
  };
}
//通过自定义的bind方法来绑定事件
btn.addEventListener("click",bind(handler.handlerClick,handler),false);

这样就可以成功的将this的指向改变,这也是很多javascript第三方库绑定函数的方法。值得一提的是,ES5中自带就有bind方法,这样就不用我们再去自定义一个bind了:

//ES5中自带就有bind方法,就不需要我们自定义bind方法了。
//使用自带的bind方法
btn.addEventListener("click",handler.handlerClick.bind(handler),false);

函数柯里化

什么叫做函数柯里化呢?其实就是function currying的翻译。curry是咖喱的意思,呵呵。好了,回归正题,currying可以理解为就是用于创建已经设置好了一个或多个参数的函数。实现方法和函数绑定一样,都是通过闭包来返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数。

//再来说说函数柯里化
//概念:用于创建已经设置好了一个或多个参数的函数,可以理解为函数中套函数
function add(num1,num2){
  return num1+num2;
}
function curriedAdd(num3){
  return add(5,num3);
}
document.write(add(2,3)+"<br>");//5
document.write(curriedAdd(3));//8
//上面的例子可以展示柯里化的概念

上面的例子虽然不是柯里化函数,但是可以展示其概念。下面我们介绍下创建函数柯里化的通用方法:

//下面介绍创建函数柯里化的通用方法
function curry(fn){
  var args = Array.prototype.slice.call(arguments,1);
  return function(){
    var innerArgs = Array.prototype.slice.call(arguments);
    var finalArgs = args.concat(innerArgs);//将innerArgs拼接到args后
    return fn.apply(null,finalArgs);
  }
}
//使用方法如下:
var curriedAdd = curry(add,5);
document.write(curriedAdd(3)+"<br>");//8
var curriedAddB = curry(add,5,10);
document.write(curriedAddB()+"<br>");//15
//可以看到参数灵活多变

也许看到这里,还不能够理解到底有什么作用,那么,我们可以将其和函数绑定结合起来,实现随意数量的传递参数:

//这样就可以在处理事件程序时传递其他参数了。
//比如下例子:,注意我们传入了name参数
var handlerB = {
  message:‘消息来了!‘,
  handlerClick : function(name,event){
    document.write(this.message+":"+name);
  }
}
btn.addEventListener("click",curriedBind(handlerB.handlerClick,handler,‘liufang‘),false);//消息来了!:liufang

ES5中自带的bind方法同样已实现了柯里化,使用方法如下:

//ES5中的bind已经实现了柯里化,所以可以直接使用:
btn.addEventListener("click",handlerB.handlerClick.bind(handlerB,"liufangagain"),false);//消息来了!:liufangagain

函数绑定和函数柯里化提供了强大的动态函数功能,它们可以用于创建复杂的算法和功能,但是会带来额外的开销。

本文全部实例地址: demo

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 08:27:57

深入理解javascript之函数的相关文章

重新理解javascript回调函数

把函数作为参数传入到另一个函数中.这个函数就是所谓的回调函数 经常遇到这样一种情况,某个项目的A层和B层是由不同的人员协同完成.A层负责功能funA,B层负责funcB.当B层要用到某个模块的数据,于是他对A层人员说,我需要你们提供满足某种需求的数据,你给我提供一个接口. A层的人员说:我给你提供数据,怎么展示和处理则是B的事情. 当然B层不可能为你每个需求都提供一个数据接口,B给A提供一个通过的接口.B得到数据,然后B写函数去展示. 即,你需要和其他人合作,别人提供数据,而你不需要关注别人获取

理解javascript 回调函数

原文:理解javascript 回调函数 ##回调函数定义 百度百科:回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如

理解JavaScript中函数的使用

函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解. JavaScript中的函数不同于其他的语言,每个函数都是作为一个对象被维护和运行的.通过函数对象的性质,可以很方便的将一个函数赋值给一个变量或者将函数作为参数传递.在继续讲述之前,先看一下函数的使用语法: function func1(…){…} var func2=function(…){…}; var func3=function func4(…){…}; var func5=new Function(

JavaScript大杂烩2 - 理解JavaScript的函数

JavaScript中的字面量 书接上回,我们已经知道在JavaScript中存在轻量级的string,number,boolean与重量级的String,Number,Boolean,而且也知道了之间的区别.这里补充一点,直接使用字面量定义的变量都是属于前一种类型,例如: var name = 'Frank'; 此外大多数的内置操作返回的也都是前一种类型,这是必须的. function是第一等公民 与别的语言不同,在JavaScript中,函数是作为数据类型存在的,所以函数具有数据的静态行为.

深入理解javascript 匿名函数和闭包

代码如下: (function(){ //这里忽略jQuery所有实现 })(); (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我就迷糊了.为什么只有一个匿 名函数又没看到运行(当然是运行了……),就能有jQuery这么个函数库了?于是,我抱着疑问来到CSDN.结果相信现在很多人都很清楚了(因为在我之 后也不乏来者,呵呵~).当一个匿名函数被括起来,然后再在后面加

理解JavaScript Call()函数原理。

最近在做面试题的过程中偶然碰到关于call函数的问题.然后再百度上查了查.偶然看到一篇文章:JavaScript中的call.apply.bind深入理解 抛开其对call函数基本概念的介绍还有其他原理的介绍.其中一段函数吸引了我. function fn1(){ console.log(1); } function fn2(){ console.log(2); } fn1.call(fn2); //输出 1 fn1.call.call(fn2); //输出 2 对于 fn1.call(fn2)

JavaScript调用函数的方法

摘要:这篇文章详细的介绍了Javascript中各种函数调用的方法及其原理,对于理解JavaScript的函数有很大的帮助! 一次又一次的,我发现,那些有bug的Javascript代码是由于没有真正理解Javascript函数是如何工作而导致的(顺便说一下,许多那样的代码是我写的).JavaScript拥有函数式编程的特性,当我们选择面对它的时候,这将成为我们前进的阻碍.  作为初学者,我们来测试五种函数调用的方法,从表面来看我们会认为那些函数与C#中函数的作用非常相似,但是我们一会儿可以看到

获取JavaScript异步函数的返回值

今天研究一个小问题: 怎么拿到JavaScript异步函数的返回值? 1.错误尝试 当年未入行时,我的最初尝试: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script> function getSomething() {  var r = 0;  setTimeout(function() {  r = 2;  }, 10);  return r; } function compute() {  var x = getSomething();  alert

javascript 回调函数(转)

一,回调函数定义 百度百科:回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫做匿名回调函