zoukankan      html  css  js  c++  java
  • 钩子机制(hook)

    钩子是编程惯用的一种手法,用来解决一种或多种特殊情况的处理。

    简单来说,钩子就是适配器原理,或者说是表驱动原理,我们预先定义了一些钩子,在正常的代码逻辑中使用钩子去适配一些特殊的属性,样式或事件,这样可以让我们少写很多 else if 语句。

    如果还是很难懂,看一个简单的例子,举例说明 hook 到底如何使用:

    现在考公务员,要么靠实力,要么靠关系,但领导肯定也不会弄的那么明显,一般都是暗箱操作,这个场景用钩子实现再合理不过了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // 如果不用钩子的情况
    // 考生分数以及父亲名
    function examinee(name, score, fatherName) {
        return {
            name: name,
            score: score,
            fatherName: fatherName
        };
    }
      
    // 审阅考生们
    function judge(examinees) {
        var result = {};
        for (var in examinees) {
            var curExaminee = examinees[i];
            var ret = curExaminee.score;
            // 判断是否有后门关系
            if (curExaminee.fatherName === 'xijingping') {
                ret += 1000;
            else if (curExaminee.fatherName === 'ligang') {
                ret += 100;
            else if (curExaminee.fatherName === 'pengdehuai') {
                ret += 50;
            }
            result[curExaminee.name] = ret;
        }
        return result;
    }
      
      
    var lihao = examinee("lihao", 10, 'ligang');
    var xida = examinee('xida', 8, 'xijinping');
    var peng = examinee('peng', 60, 'pengdehuai');
    var liaoxiaofeng = examinee('liaoxiaofeng', 100, 'liaodaniu');
      
    var result = judge([lihao, xida, peng, liaoxiaofeng]);
      
    // 根据分数选取前三名
    for (var name in result) {
        console.log("name:" + name);
        console.log("score:" + score);
    }

    可以看到,在中间审阅考生这个函数中,运用了很多 else if 来判断是否考生有后门关系,如果现在业务场景发生变化,又多了几名考生,那么 else if 势必越来越复杂,往后维护代码也将越来越麻烦,成本很大,那么这个时候如果使用钩子机制,该如何做呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // relationHook 是个钩子函数,用于得到关系得分
    var relationHook = {
        "xijinping": 1000,   
        "ligang": 100,
        "pengdehuai": 50,
       // 新的考生只需要在钩子里添加关系分
    }
     
    // 考生分数以及父亲名
    function examinee(name, score, fatherName) {
        return {
            name: name,
            score: score,
            fatherName: fatherName
        };
    }
      
    // 审阅考生们
    function judge(examinees) {
        var result = {};
        for (var in examinees) {
            var curExaminee = examinees[i];
            var ret = curExaminee.score;
            if (relationHook[curExaminee.fatherName] ) {
                ret += relationHook[curExaminee.fatherName] ;
            }
            result[curExaminee.name] = ret;
        }
        return result;
    }
      
      
    var lihao = examinee("lihao", 10, 'ligang');
    var xida = examinee('xida', 8, 'xijinping');
    var peng = examinee('peng', 60, 'pengdehuai');
    var liaoxiaofeng = examinee('liaoxiaofeng', 100, 'liaodaniu');
      
    var result = judge([lihao, xida, peng, liaoxiaofeng]);
      
    // 根据分数选取前三名
    for (var name in result) {
        console.log("name:" + name);
        console.log("score:" + score);
    }

    可以看到,使用钩子去处理特殊情况,可以让代码的逻辑更加清晰,省去大量的条件判断,上面的钩子机制的实现方式,采用的就是表驱动方式,就是我们事先预定好一张表(俗称打表),用这张表去适配特殊情况。当然 jQuery 的 hook 是一种更为抽象的概念,在不同场景可以用不同方式实现。

    看看 jQuery 里的表驱动 hook 实现,$.type 方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    (function(window, undefined) {
        var
            // 用于预存储一张类型表用于 hook
            class2type = {};
     
        // 原生的 typeof 方法并不能区分出一个变量它是 Array 、RegExp 等 object 类型,jQuery 为了扩展 typeof 的表达力,因此有了 $.type 方法
        // 针对一些特殊的对象(例如 null,Array,RegExp)也进行精准的类型判断
        // 运用了钩子机制,判断类型前,将常见类型打表,先存于一个 Hash 表 class2type 里边
        jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
            class2type["[object " + name + "]"] = name.toLowerCase();
        });
     
        jQuery.extend({
            // 确定JavaScript 对象的类型
            // 这个方法的关键之处在于 class2type[core_toString.call(obj)]
            // 可以使得 typeof obj 为 "object" 类型的得到更进一步的精确判断
            type: function(obj) {
     
                if (obj == null) {
                    return String(obj);
                }
                // 利用事先存好的 hash 表 class2type 作精准判断
                // 这里因为 hook 的存在,省去了大量的 else if 判断
                return typeof obj === "object" || typeof obj === "function" ?
                    class2type[core_toString.call(obj)] || "object" :
                    typeof obj;
            }
        })
    })(window);

    这里的 hook 只是 jQuery 大量使用钩子的冰山一角,在对 DOM 元素的操作一块,attr 、val 、prop 、css 方法大量运用了钩子,用于兼容 IE 系列下的一些怪异行为。在遇到钩子函数的时候,要结合具体情境具体分析,这些钩子相对于表驱动而言更加复杂,它们的结构大体如下,只要记住钩子的核心原则,保持代码整体逻辑的流畅性,在特殊的情境下去处理一些特殊的情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var someHook = {
        get: function(elem) {
            // obtain and return a value
            return "something";
        },
        set: function(elem, value) {
            // do something with value
        }
    }

    从某种程度上讲,钩子是一系列被设计为以你自己的代码来处理自定义值的回调函数。有了钩子,你可以将差不多任何东西保持在可控范围内。

  • 相关阅读:
    处理字符串拼接成想要的数组
    json 压缩中文不转码
    MySQL主从同步机制及同步中的问题处理
    mysql主从复制亲测,以及注意事项
    windows下mysql和linux下mysql主从配置
    拯救U盘之——轻松修复U盘“无法访问”的故障
    MUI框架开发HTML5手机APP(一)--搭建第一个手机APP
    UI之富文本编辑器-UEditor
    弹性布局详解——5个div让你学会弹性布局
    内置函数:min 用法
  • 原文地址:https://www.cnblogs.com/wang985850293/p/5623626.html
Copyright © 2011-2022 走看看