zoukankan      html  css  js  c++  java
  • JavaScript基础CallBack函数(015)

    前面提到,函数对象是可以作为参数传递给另一函数的,这时,作为参数的函数如果在内部被执行,那么它就是个回调函数(Callback):

    function writeCode(callback) {
        // do something...
        callback();
        // ...
    }
    function introduceBugs() {
        // ... make bugs
    }
    writeCode(introduceBugs);
    

     在上面的代码里,introduceBugs就作为writeCode的参数,在writeCode函数的执行过程中被调用。因此introduceBugs就是一个回调(CallBack)函数。
    下面给出一个更有实际意义的回调函数。假设我们有一个findNodes函数,它可以通过一个复杂的逻辑,在一个很大的数组中找到满足某个条件的所有结点,并返回这些结点:

    var findNodes = function () {
        var i = 100000, // big, heavy loop
            nodes = [], // stores the result
            found; // the next node found
        while (i) {
            i -= 1;
            // complex logic here...
            nodes.push(found);
        }
        return nodes;
    };
    

     一般来说我们都希望函数的功能单一化,所以这个函数只负责把满足某件的结点找到,并返回。然后我们写另外一个函数hide,可以把给定的一堆结点隐藏,这 个函数接受一个结点的数组作为参数,并把数组中的结点一个一个地隐藏。结合这两个函数,我们就可以完成一个组合功能,即找到一些结点,并把它们隐藏:

    var hide = function (nodes) {
        var i = 0, max = nodes.length;
        for (; i < max; i += 1) {
            nodes[i].style.display = "none";
        }
    };
    
    
    // executing the functions
    hide(findNodes());
    

     看起来挺好。不过这种实现方法的执行效率并不高。这两个函数都需要进行一个很长的循环,则实际上,如果每找到一个满足就条件的结点,就立即把它隐藏,这样效率更高:因为只需要循环1次。为了实践这个想法,但依然把两个任务用不同的函数来实现,我们用回调的方式来做:

    // refactored findNodes() to accept a callback
    var findNodes = function (callback) {
        var i = 100000,
            nodes = [],
            found;
    
    
        // check if callback is callable
        if (typeof callback !== "function") {
            callback = false;
        }
    
        while (i) {
            i -= 1;
    
            // complex logic here...
    
            // now callback:
            if (callback) {
                callback(found);
            }
    
            nodes.push(found);
        }
        return nodes;
    };
    

     findNodes这时还是返回满足条件的所有结点,但它也接受一个回调函数,用于给每个满足条件的结点执行一些任务。这个任务就交给回调函数来声明。下面是具体的回调函数hide:

    // a callback function
    var hide = function (node) {
        node.style.display = "none";
    };
    
    
    // find the nodes and hide them as you go
    findNodes(hide);
    

     当然,如果hide只服务于findNodes,有时我们不需要给它一个名字,从而把它声明为一个匿名的回调函数:

    // passing an anonymous callback
    findNodes(function (node) {
        node.style.display = "block";
    });
    

     回调函数中的this
    当回调函数中使用了this,比如,这个回调函数其实是对象myapp中的一个方法paint:

    var myapp = {};
    myapp.color = "green";
    myapp.paint = function (node) {
        node.style.color = this.color;
    };
    

     这时我们有一个全局的函数findeNodes()接受一个回调函数:

    var findNodes = function (callback) {
        // ...
        if (typeof callback === "function") {
            callback(found);
        }
        // ...
    };
    

     这时如果执行 findNodes(myapp.paint),并不能达到预期的结果。因为myapp.paint中的this指针在声明的时候指向的是对象中的属性, 也就是那个对象本身,但当myapp.paint作为回调函数在全局的函数findNodes时执行是,this指针在执行期间指向的就变成了全局的 this了(如果在浏览器中,就是dom对象)。
    解决方法是把回调函数所属的对象也一并传递给findNodes,然后在执行回调函数时指定它所属的对象:

    findNodes(myapp.paint, myapp);
    

     所以findNodes修改为这样:

    var findNodes = function (callback, callback_obj) {
        //...
        if (typeof callback === "function") {
            callback.call(callback_obj, found);
        }
       // ...
    };
    

     这样看起来有点啰嗦,因为对象的名字在参数列表里出现了两次。我们也可以把这个回调函数的名字用字符串的方式传递:

    findNodes("paint", myapp);
    

     这里findNodes就相应的修改为:

    var findNodes = function (callback, callback_obj) {
        if (typeof callback === "string") {
            callback = callback_obj[callback];
        }
        //...
        if (typeof callback === "function") {
            callback.call(callback_obj, found);
        }
       // ...
    };
    
  • 相关阅读:
    memory prefix out omni,over,out,od,octa ~O
    killl prefix out macro mis mal micro -m
    memory prefix mini mono multi out _m 5
    memory prefix inter,intra,intro,iso out 5
    memory prefix il ir im in out 3 i
    memory prefix twi,tri,trans ,tetra out 4
    memory prefix retro,re out 2
    memory prefix un,under,uni out1
    Python调用libsvm
    yolov3 训练数据集
  • 原文地址:https://www.cnblogs.com/Bryran/p/3964877.html
Copyright © 2011-2022 走看看