JS学习笔记 - 回调函数

本文章记录本人在学习 JavaScript 中看书理解到的一些东西,加深记忆和而且整理记录下来,方便以后的复习。node

什么是回调函数

js里函数都是对象,这表示它们能够做为参数传递给其余的函数。举例:当函数b()做为参数传递给函数a(),那么在某一时刻函数a()可能会执行或者调用函数b()。这种状况下,函数b()就被称为回调函数,也能够简称叫作回调(下面是栗子)。数组

JavaScript'use strict';

function a(callback) {
    callback();
}

function b() {
    console.log('hello callback');
}

a(b); // 注意 b() 做为参数传递给 a() 的时候是不须要带括号的

回调函数示例

假设有一个通用的函数执行一些复杂的处理工做,而且返回结果为一个大块数据(下面是栗子)。app

JavaScriptvar findeNodes = function () {
    var i = 10000,
        node = [],
        found;

    while (i) {
        i -= 1;
        node.push(found);
    }

    return nodes;
}

上面代码定义函数findNodes(),它的任务是抓取页面的dom tree,并返回一个你要的页面元素数组。dom

在定义一个函数hide(),顾名思义它的做用是隐藏页面中的节点(下面是栗子)。ide

JavaScriptvar hide = function (nodes) {
    for (var i = 0; i < nodes.length; i += 1) {
        nodes[i].style.display = 'block';
    }
}

// 执行函数
hide(findeNodes());

好了,要的效果都实现了,可是实现倒是低效的。由于hide()必须再次循环由findNodes()返回的数组节点。若是能避免这种循环,只须要在findNodes()中选择即可隐藏节点,那么这将是更高效的方式。可是若是在findNodes()中实现隐藏逻辑的话,因为检索和修改逻辑耦合,那么他再也不是通用的函数。面对这种问题的解决方法是采用回调模式,能够将所以节点逻辑以回调函数方式传递给findNodes()并委托执行(下面是栗子)。函数

JavaScript// 重构 findeNodes() 函数,并接受一个回调函数

var findeNodes = function (callback) {
    var i = 10000,
        nodes = [],
        found;

    while (i) {
        i -= 1;

        // 如今运行回调函数
        if (typof callback === 'function') {
            callback();
        }

        nodes.push(found);
    }
    return found;
}

上面的代码只是作了对callback是否存在进行了判断,若是存在的话吗,那么就执行该函数。其中,回调函数是可选的,所以后续的findeNodes()仍然能够想之前同样使用,而不会破坏以来旧API的原始代码。学习

如今hide的实现就简单多了,由于它不须要再去循环遍历全部的节点了(下面是栗子)。this

JavaScript// 回调函数
var hide = function (nodes) {
    nodes.style.display = 'none';
}

// 找到指定的节点,并在后续执行中隐藏
findeNodes(hide);

回调函数与做用域

在上一个栗子中,回调函数执行的语句是这样的:callback(parameters)code

虽然上面那句在大多数的场景上都是有效的,可是总会有一些场景,其回调函数并非一次性的匿名函数或者全局函数,而是对象的方法。若是该函数使用this来引用它所的属性,这可能有是一个坑了(下面是栗子)。对象

JavaScript// 假设回调函数是 paint(),它是一个名为 myapp 的对象的方法
var myapp = {};
myapp.color = 'green';
myapp.paint = function (nodes) {
    nodes.style.color = this.color;
}

// 而后用到上一个栗子的 findeNodes() 
findeNodes(myapp.paint); //

坑:this.color没有被定义,由于findeNods()是一个全局函数,所以,对象的this是指向window的。

解决的方法有:

  • 另外传递该回调函数的所属对象。这样就须要修改一下findNodes()函数(下面是栗子)。
JavaScriptvar findNodes = function (callback, callback_obj) {
    // ...
    if (typof callback === 'function') {
            callback.call(callback_obj, found);
    }
    // ...
}

// 执行函数
findNodes(myapp.paint, myapp);

主要是经过call、apply来修改函数运行时的this指向。

  • 而后接着修改上面的方法,将方法做为字符串传递,所以就不用两次输入该对象的名称(下面是栗子)。
JavaScriptvar findNodes = function (callback, callback_obj) {
    // ...
    if (typof callback === 'string') {
        callback = callback_obj[callback];
    }
    // ...
    if (typof callback === 'function') {
            callback.call(callback_obj, found);
    }
    // ...
}

// 执行函数
findNodes('paint', myapp);

最后,若是文章有什么错误和疑问的地方,请指出。与sf各位共勉!

相关文章
相关标签/搜索