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);
        }
       // ...
    };
    
  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/Bryran/p/3964877.html
Copyright © 2011-2022 走看看