JS学习笔记 - 回调函数

简介: JS学习笔记 - 回调函数

原文链接: segmentfault.com

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


什么是回调函数

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

 

'use strict';
function a(callback) {
    callback();
}
function b() {
    console.log('hello callback');
}
a(b); // 注意 b() 作为参数传递给 a() 的时候是不需要带括号的


回调函数示例

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

 

var findeNodes = function () {
    var i = 10000,
        node = [],
        found;
    while (i) {
        i -= 1;
        node.push(found);
    }
    return nodes;
}

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

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

 

var hide = function (nodes) {
    for (var i = 0; i < nodes.length; i += 1) {
        nodes[i].style.display = 'block';
    }
}
// 执行函数
hide(findeNodes());

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

 

// 重构 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的实现就简单多了,因为它不需要再去循环遍历所有的节点了(下面是栗子)。

 

// 回调函数
var hide = function (nodes) {
    nodes.style.display = 'none';
}
// 找到指定的节点,并在后续执行中隐藏
findeNodes(hide);


回调函数与作用域

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

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

 

// 假设回调函数是 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()函数(下面是栗子)。

 

var findNodes = function (callback, callback_obj) {
    // ...
    if (typof callback === 'function') {
            callback.call(callback_obj, found);
    }
    // ...
}
// 执行函数
findNodes(myapp.paint, myapp);

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

  • 然后接着修改上面的方法,将方法作为字符串传递,因此就不用两次输入该对象的名称(下面是栗子)。

 

var 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各位共勉!


目录
相关文章
|
28天前
|
JavaScript 前端开发 API
Vue学习笔记3:对比纯JavaScript和Vue实现数据更新的实时视图显示
Vue学习笔记3:对比纯JavaScript和Vue实现数据更新的实时视图显示
|
5月前
|
JavaScript 前端开发 Go
动态加载与异步加载 JavaScript 详解:加载远程js,加载成功后执行回调函数
动态加载与异步加载 JavaScript 详解:加载远程js,加载成功后执行回调函数
966 2
|
5月前
|
JavaScript 前端开发 UED
在 JavaScript 中,异步编程和回调函数是处理非阻塞操作(如网络请求、文件读写等)的重要工具
【5月更文挑战第10天】JavaScript中的异步编程和回调函数用于处理非阻塞操作,提高应用响应性和吞吐量。异步编程通过回调函数、Promises和async/await等方式实现,避免程序因等待操作完成而阻塞。回调函数是异步操作完成后调用的函数,常用于处理网络请求等。然而,回调函数存在嵌套问题和错误处理困难,因此出现了Promises和async/await等更优解决方案。
42 3
|
14天前
|
JavaScript API
Node.js 回调函数
10月更文挑战第3天
12 0
|
15天前
|
JavaScript 前端开发
【干货分享】JavaScript学习笔记分享
【干货分享】JavaScript学习笔记分享
49 0
|
1月前
|
Web App开发 前端开发 JavaScript
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
|
3月前
|
JavaScript 前端开发 API
Node中的AsyncLocalStorage 使用问题之Node.js将 JavaScript 层的 nativeHooks 注册到 C++ 层的问题如何解决
Node中的AsyncLocalStorage 使用问题之Node.js将 JavaScript 层的 nativeHooks 注册到 C++ 层的问题如何解决
|
4月前
|
存储 前端开发 JavaScript
回调函数是JavaScript中处理异步编程的常见模式,常用于事件驱动和I/O操作。
【6月更文挑战第27天】回调函数是JavaScript中处理异步编程的常见模式,常用于事件驱动和I/O操作。它作为参数传递给其他函数,在特定条件满足或任务完成后被调用。例如,`asyncOperation`函数接受回调函数`handleResult`,模拟异步操作后,调用`handleResult`传递结果。这样,当异步任务完成时,`handleResult`负责处理结果。
31 1
|
4月前
|
前端开发 JavaScript
JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。
【6月更文挑战第22天】JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。回调是基础,用于在操作完成后执行函数;Promise管理异步状态,支持链式调用;async/await提供同步代码外观,简化错误处理。每种技术在处理耗时任务时都起着关键作用。
43 3
|
4月前
|
前端开发 JavaScript 开发者
JavaScript基础-异步编程:回调函数
【6月更文挑战第12天】本文介绍了JavaScript中的异步编程基础,重点讨论回调函数。回调函数是处理延迟操作的关键,常见于事件监听、定时器、Ajax请求和文件操作。然而,它们可能导致回调地狱、错误处理不一致和控制流混乱等问题。为了解决这些问题,文章推荐使用Promise链、async/await来扁平化异步逻辑,并提供了相关代码示例,强调了现代JavaScript特性的优势,以提升代码可读性和可维护性。
91 7