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 条评论
登录 后参与评论

相关文章

来自专栏ArrayZoneYour的专栏

借助Babel 7和Webpack构建React Toolchain

React不是完全开箱即用的。它使用了一些最近node才支持的关键字和语法(在本教程中我使用了v 9.3.0版本)。因此需要一些很麻烦的设置,但是Faceboo...

2524
来自专栏Jerry的SAP技术分享

SAP Fiori应用Footerbar区域按钮的高亮显示逻辑

如果您够细心,您或许会发现有的SAP Fiori应用的footerbar区域内的按钮有高亮显示,有的则没有。

1948
来自专栏小尘哥的专栏

使用bootstrap-Validator校验表单

前端UI框架选择bootstrap,那么bootstrap-Validator作为表单校验是一个不错的选择。

1693
来自专栏小狼的世界

如何生成eot字体

前一段时间听闻Google退出ubuntu字体的时候,使用了一下,从而了解到 font-face 的用法:

1172
来自专栏WindCoder

基于zepto的微信手机端微场景HTML5页面特效

page处是管理图片的,在改div中添加删除图片及图片中的相关组件,如在div标签为page page-9中添加的Button组件。

2181
来自专栏赵俊的Java专栏

Hexo优化 --- 添加复制功能

7501
来自专栏DeveWork

自定义WordPress 密码文章提示文字

WordPress 默认的密码提示文字是这样的:This post is password protected. To view it please enter...

3667
来自专栏向治洪

微信小程序开发入门篇

本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果。 开发准备工作 获取微信小程序的 AppID 登录 https://mp.wei...

3886
来自专栏liulun

在VSCode中编辑HTML文档时,在Dom标签上写style属性时智能提示的问题

首先在VSCode中打开一个HTML文件 然后点右下角的“选择语言模式” image.png 然后点击配置HTML语言的基础设置 image.png 然后在...

2218
来自专栏知无涯

WEB前端:element.style覆盖了我想修改的样式!

3948

扫码关注云+社区

领取腾讯云代金券