zoukankan      html  css  js  c++  java
  • 函数式编程初探之回调

    上班无聊,先废话几句。

    我是个很懒的人,博客几乎不更新,代码也不想撸,有活干活,没活刷豆瓣玩农场。
    技术学习进入瓶颈。不知从何提高,自己也没什么动力。现在就是上班无聊,为了防止脑子生锈老年痴呆,顺便看看文章捣鼓捣鼓啦。
    作为一个妹纸,我的远大理想永远是怎么把自己打扮的更好看 = =
     
    回调 Callbak
    这个东西大家都听说过,最初我也很迷茫,只是听说不知其为何物。
    说白了,就是把函数作为参数嘛!关回调啥事呀。回调只是它的应用所在。
    经典的Jquery的Ajax我不想谈,在这里谈谈JS原生的Array的Map方法。
     
    代码是这个样子 ↓↓ 
    array.map(callback,[ thisObject]);
    [].map(function(value, index, array) {
        // ...
    });
    这是Array对象的原型方法,它有两个参数,第一个参数是callback,第二个参数为this关键字的绑定,可省略。
    map是顾名思义呢是一个映射函数,对数组里的每个对象依次执行Callback,返回一个新的数组。
    文字不是很明白,看实例。
     
    var misa = [1, 2, 3],
    misamisa = misa.map(function(value, index) {
        return value * value
    }}
    我觉得这个例子有点糟。(最近有点傻不会写例子了 T^T 凑合着)
    对misa数组里的每个对象,执行value * value,也就是返回平方。得到的结果就是一个新的数组[1, 4, 9]
    function(value, index) 这个匿名函数,在misa.map 方法的生命周期里执行。这就是传说中的回调。
     
    总有人搞不清回调函数里的参数是哪来的。
    比如$.ajax里的function(data) ,  addEventListener里的event。经常有人问我这样的问题。
    一开始我也是这样啦。我们自己来写一个map方法来有助于更好的理解吧!
      var a = [1, 2, 3]
    
      Array.prototype.mymap = function (callback) {
        var length = this.length,
        b = new Array;
        for(var i = 0; i < length; i++) {
          b[i] = callback(this[i], i)
        }
        return b;
      }
    
      var b = a.mymap(function(val) {
        return val * val
      })
    mymap模拟实现了map方法。callback里的参数,就是这么传过来的。跟命名完全没有关系,跟参数的顺序才有关系。
    这里我没有用到第二个参数i,所以在调用的时候没有写。
     
    当然,你也可以把callback提取出来写在外面。写成这样 ↓↓
    var callback = function(val, index) {
        console.log(index)
        return val * val
      }
      var b = a.mymap(callback)

    下面来讲一讲在实际的应用中,新手容易犯的错误。比如JS的事件监听。一般的定法是这样

      document.getElementById('btn').addEventListener('click', function(event) { 
        console.log(event) 
      }, false)

    如果想把第二个参数抽出来,可以这样写

    function clickBtn(val) { 
        console.log(val) 
      } 
    document.getElementById(
    'btn').addEventListener('click', clickBtn, false)

     而不是这样 ↓↓

    /* 错误代码 */
    document.getElementById('btn').addEventListener('click', clickBtn(event), false)
    上面代码犯了什么错误呢,就是没理解clickBtn是作为addEventListener方法的一个参数而存在的。
    clickBtn的参数,是在addEventListener的执行过程中传入的。上面的写法,其实是把clickBtn(event)执行后的结果做为参数传入。
     
    还有一种常见的代码
      var img = document.getElementsByTagName('img') 
      for(var i = 0; i < img.length; i++) { 
          img[i].addEventListener('click', function() { 
            alert(i + 1) 
          }, false) 
      }
    假设页面上有十张图片,我们的预期结果是点第一张弹出1,第二张弹出2……而实际结果是每张都alert 11。即i的最终值。
    为什么会这样。因为addEventListener并没有记住i,也没有理由记住i。i作为循环变量的生命周期只在for循环内部,addEventListener为IMG标签绑定点击事件的监听。而真正执行点击的时候,函数处在全局环境。因为i始终为循环结束后的值 11。
     
    那么如何把i带入到addEventListener内部呢?
    我们可以用闭包。
      for(var i = 0; i < img.length; i++) { 
          (function() { 
            var _i= i; 
            img[i].addEventListener('click', function() { 
              alert(_i + 1) 
            }, false) 
          })() 
      }
    至于闭包是如何做到的,需要用更长的篇幅去讨论了。这里暂不深入。
  • 相关阅读:
    3个检测浏览器UserAgent信息的网站
    linux系统下配置网桥(CentOS 5.5)
    squid封禁不带UserAgent的请求
    iptables透明网桥无法使用透明代理错误
    Squid修改用户浏览器的Useragent信息
    MySQL主从复制(MasterSlave)与读写分离(MySQLProxy)实践
    js中格式化时间
    js获取当前月的第一天和最后一天
    JS String.toDate
    Js获取当前日期时间及其它操作
  • 原文地址:https://www.cnblogs.com/misadancer/p/3730280.html
Copyright © 2011-2022 走看看