javascript callback函数的理解与使用

来源:互联网 发布:人工智能的现状论文 编辑:程序博客网 时间:2024/05/20 00:13

回调函数定义: 

 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

  在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。因此callback 不一定用于异步,一般同步(阻塞)的场景下也经常用到回调,比如要求执行某些操作后执行回调函数。

  回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。

  通俗形象的解释: 把函数f2当做一个参数传给函数f1 并且在f1里适当的时间执行f2
  

function f1(f2) {    //f1要执行的一些代码    if (f2 && typeof(f2) === "function") { //对f2做判断是否存在并且是一个函数        f2();    }}

注释:
    参数里的f2是一个指向f2这个函数的指针所以f2后面不能加括号,而f1内部的f2后面要有括号 因为这时我们要调用执行f2 ,所以要写f2()
结果:

//"我是f1",“我是f2”

回调函数的传递

$.get('myhtmlpage.html',myCallBack); //这是对的$.get('myhtmlpage.html',myCallBack('foo','bar'));   //这是错的,若要带参数实现如下$.get('myhtmlpage.html',function(){  //带参数的函数表达式  myCallBack('foo','bar');});

回调什么时候执行

回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。

例子

//模拟查找页面中的dom节点,将查找到的节点存在数组里面统一返回   //此函数只用于查找不对dom节点做任何的逻辑处理   var findNodes = function(){    var i = 100000;//大量的循环,    var nodes = [];//用于存储找到的dom节点    var found;    while(i){     i -=1;     nodes.push(found);    }    return nodes;   }   //将查找找到的dom节点全部隐藏   var hide = function(nodes){    var i = 0,     max = nodes.length;    for(;i<max;i++){ //findNodes后面有括号代表立即执行,先执行findNodes()然后执行hide()< hide(findNodes()); 执行函数 } ; nodes[i].style.display="none"}

方法是低效的,以为hide()必须再次遍历有findNodes()返回的数组节点,如何避免这种多余的循环呢。
我们不能直接在findNodes中对查询到的节点进行隐藏(这样检索就可修改逻辑耦合了),那么他就不再是一个通用函数了。

//重构findNodes以接受一个回调函数    var findNodes = fucntion(callback){     var i = 100000,      nodes = [],      found;     //检查回调函数是否可用调用的     if(typeof callback !== 'function'){      callback = false;     }     while(i){      i -= 1;      if(callback){       callback(found);      }      nodes.push(found);     }     return nodes;    }    //回调函数    var hide = function(node){     node.style.display = 'none ';    }    //找到后续节点并在后续执行中对其进行隐藏  findNodes(hide);//先执行findNodes然后执行hide,当然回调函数也可以在调用主函数时创建:findNodes(function(node){node.style.display = 'none';});

独白:

看完例子,我的想法是为什么要把隐藏定义在回调里面。我直接查找到dom元素。然后隐藏就好了。
函数封装的思想:这样能降低代码耦合度,当样式变了,辣么直接改hide函数就好,而不用动findNode

回调函数的使用场合

    资源加载:动态加载js文件后执行回调,加载iframe后执行回调,ajax操作回调,图片加载完成执行回调,AJAX等等。
    DOM事件及Node.js事件基于回调机制(Node.js回调可能会出现多层回调嵌套的问题)。

    setTimeout的延迟时间为0,这个hack经常被用到,settimeout调用的函数其实就是一个callback的体现

    链式调用:链式调用的时候,在赋值器(setter)方法中(或者本身没有返回值的方法中)很容易实现链式调用,而取值器(getter)相对来说不好实现链式调用,因为你需要取值器返回你需要的数据而不是this指针,如果要实现链式方法,可以用回调函数来实现setTimeout、setInterval的函数调用得到其返回值。由于两个函数都是异步的,即:他们的调用时序和程序的主流程是相对独立的,所以没有办法在主体里面等待它们的返回值,它们被打开的时候程序也不会停下来等待,否则也就失去了setTimeout及setInterval的意义了,所以用return已经没有意义,只能使用callback。callback的意义在于将timer执行的结果通知给代理函数进行及时处理。

0 0