JS 回调模式

1. 回调示例

如果有个模块 findeNodes() ,任务是找到期望的 DOM 元素并使用 hide() 处理:

function findNodes() {
    var i = 10000, nodes = [], found
    while (i--) {
        // ...复杂逻辑,筛选出符合的元素 found
        nodes.push(found)
    }
    return nodes
}

function hide(nodes) {
    for (let i = 0, max = nodes.length; i < max; i++) {
        nodes[i].style.display = 'none'
    }
}
hide(findNodes())

2. 改进

可以看到函数 findNodes()hide() 分别两次进行了循环,这是十分低效的,如果要避免这种重复循环,并且只要在 findNodes() 中选择的时候就进行 hide() 那么将是高效的实现方式。如果在 findNodes() 中实现修改逻辑,由于检索和修改逻辑耦合,那么它将不再是一个通用函数。对这种问题的解决方法是采用回调模式

可以将节点隐藏逻辑以回调函数的方式传递给 findNodes() 并委托执行:

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

    if (typeof callback !== 'function') {    // 检查参数是否为可调用
        callback = false
    }

    while (i--) {
        // ...复杂逻辑,筛选出符合的元素 found
        if (callback) {
            callback(found)
        }
        nodes.push(found)
    }
    return nodes
}

function hide(nodes) {
    nodes[i].style.display = 'none'
}

findNodes(hide)

那么现在回调函数可选,重构后加入回调函数参数的 findNodes() 仍然可以像以前一样使用,而不会破坏旧 API 的原始代码。

3. 回调与作用域

前面的例子中,回调执行的语句:callback(para),在多数情况下有效,但是如果传递的函数是对象的方法且有 this 那么回调方法里的 this 将指向的是全局对象,从而发生意外。

解决这个问题的方法是传递回调函数,并且还传递该回调函数所属的对象:

function findNodes (callback, callback_obj){
    ...
    if (typeof callback === 'function'){
        callback.call(callback_obj, found)
    }
    ...
}
findNodes (obj.sayName, obj)

当然,可以把方法作为字符串来传递,避免重复两次输入该对象的名称:

findNodes (callback, callback_obj){
    if (typeof callback === 'string'){
        callback = callback_obj[callback]
    }
    if (typeof callback === 'function'){
        callback.call(callback_obj, found)
    }
}
findNodes('sayName', Obj)

本文是系列文章,可以相互参考印证,共同进步~

  1. JS 抽象工厂模式
  2. JS 工厂模式
  3. JS 建造者模式
  4. JS 原型模式
  5. JS 单例模式
  6. JS 回调模式
  7. JS 外观模式
  8. JS 适配器模式
  9. JS 利用高阶函数实现函数缓存(备忘模式)
  10. JS 状态模式
  11. JS 桥接模式
  12. JS 观察者模式

网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~

参考:<JavaScript 模式> P65

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [译] 监测与调试 Vue.js 的响应式系统:计算属性树(Computed Tree)

    关于 Vue 的下一个主版本,公布的很多新特性引发了激烈的讨论,但其中有一个特性引起了我的注意:

    前端下午茶
  • 前端路由跳转基本原理

    目前前端三杰 Angular、React、Vue 都推介单页面应用 SPA 开发模式,在路由切换时替换 DOM Tree 中最小修改的部分 DOM,来减少原先因...

    前端下午茶
  • [译] 使用 Proxy 来监测 Javascript 中的类

    Proxy 对象(Proxy)是 ES6 的一个非常酷却鲜为人知的特性。虽然这个特性存在已久,但是我还是想在本文中对其稍作解释,并用一个例子说明一下它的用法。

    前端下午茶
  • Bullet中创建中心不在原点的碰撞体

    逍遥剑客
  • DX 已被弃用,请尽快迁移至 D8

    我们在 2017 年发布了 D8,这是一款用于取代 DX、更快的 Dex 编译器,可以生成更小的 APK。2018 年 4 月,我们宣布 D8 成为 Andro...

    Android 开发者
  • Python 系统资源信息获取工具,你用过没?

    psutil(process and system utilities)是一个跨平台的库,github、官方文档

    崔庆才
  • 安防网络摄像头互联网直播视频流媒体服务器EasyNVR输出直播流 RTMP、HTTP-FLV、 HLS 的对比分析

    随着直播行业大火,游戏、乐秀、教育、发布会等直播类产品层出不穷,能够满足各方人员的需求。在直播中,总能在其中找到适合自己的产品内容。喜欢玩游戏的可以看游戏直播,...

    EasyNVR
  • Qt编写地图综合应用15-添加删除清空重置点

    在地图应用的相关项目中,在地图上标识一些设备点,并对点进行交互这个功能用的最多的,于是需要一套机制可以动态的添加、删除、清空、重置,重置的意思是将地图中的所有点...

    feiyangqingyun
  • HTML5 性能监控API - 计时

    计时API可以测量两个预定义标记之间的性能,仅需要分别定义测量的开始和结束标记 例如 var start = performance.now(); ... ...

    dys
  • Qt编写安防视频监控系统28-摄像机点位

    摄像机点位的功能主要是在图片地图和在线离线地图上设置对应摄像机的位置,然后双击可以实时预览对应摄像机的视频,在图片地图上拖动摄像机图标到对应位置,系统会自动保存...

    feiyangqingyun

扫码关注云+社区

领取腾讯云代金券