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

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

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

钩子机制(hook)的更多相关文章

  1. [转] js中的钩子机制(hook)

    什么是钩子机制?使用钩子机制有什么好处? 钩子机制也叫hook机制,或者你可以把它理解成一种匹配机制,就是我们在代码中设置一些钩子,然后程序执行时自动去匹配这些钩子:这样做的好处就是提高了程序的执行效 ...

  2. PHP钩子机制

    什么是钩子 大家想必听过插件,wordpress插件特别多,这个就是用钩子机制实现的. 当代码在运行的过程中,我们预先在运行的几个特殊点里执行一些特殊方法:例如在运行方法(例如Blog::add的ad ...

  3. javascript钩子机制

    钩子机制是这样的,大家按照某一规则写一个方法(这个规则在方法名称上),然后页面加载完之前,统一执行所有的钩子函数. 注意callHooks方法,里面的局部变量s就是钩子函数名称中一定要有的内容.——这 ...

  4. koahub.js 0.09 发布,新增钩子机制

    koahubjs发布0.09 新增钩子机制添加钩子机制,控制器钩子和函数钩子修复自动加载bug,实现除自动加载导出的default外,还能自动加载其他的方法记koahubjs钩子开发过程在使用koah ...

  5. 【windows核心编程】系统消息与自定义钩子(Hook)使用

    一.HOOk Hook是程序设计中最为灵活多变的技巧之一,在windows下,Hook有两种含义: 1.系统提供的消息Hook机制 2.自定义的Hook编程技巧 其中,由系统提供的消息钩子机制是由一系 ...

  6. vue-router 路由钩子(hook)

    钩子(hook)—劫持机制 路由钩子(守卫钩子): 1.全局钩子2.某个路由独享的钩子3.组件内钩子 三种路由钩子中都涉及到了三个参数,官方(https://router.vuejs.org/zh-c ...

  7. jQuery 2.0.3 源码分析 钩子机制 - 属性操作

    jQuery提供了一些快捷函数来对dom对象的属性进行存取操作. 这一部分还是比较简单的. 根据API这章主要是分解5个方法 .attr()   获取匹配的元素集合中的第一个元素的属性的值  或 设置 ...

  8. 关闭钩子(shutdown hook)的作用

    DK1.3介绍了java.lang.Runtime class的addShutdownHook()方法.如果你需要在你的程序关闭前采取什么措施,那么关闭钩子(shutdown hook)是很有用的. ...

  9. JAVA虚拟机关闭钩子(Shutdown Hook)

    程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Java.Run ...

随机推荐

  1. MYSQL EXPLAIN 很慢的原因

    今天同事在查看一个SQL的执行计划的时候,EXPLAIN语句跑了2分钟.SQL命令类似: SELECT * FROM (SELECT USERID,COUNT(*) FROM TBNAME GROUP ...

  2. LINUX下动态库及版本号控制

    针对同一动态组件的不同版本链接和加载. 一.概念                  DLL HELL字面意思是DLL"灾难",是由于com组件(动态库)升级引起的程序不能运行的情况 ...

  3. WindowsForm只允许运行一个实例

    static class Program { private static Mutex onlyOne; /// <summary> /// 应用程序的主入口点. /// </sum ...

  4. itextSharp 附pdf文件解析

    一.PdfObject: pdf对象 ,有9种,对象是按照对象内涵来分的,如果按照对象的使用规则来说,对象又分为间接对象和直接对象.间接对象是PDF中最常用的对象,如前面对象集合里面的,所有对象都是间 ...

  5. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  6. 课堂笔记--Strom并发模型

    Strom并发模型:     topology是如何运行的?(可与mapreduce对比)         第一层:cluster         第二层:supervisor(host.node.机 ...

  7. uploadify图片上传发生Security Error

    今天在使用uploadify进行图片上传的时候出现security error.其根本原因是flash跨域问题.主要原因是因为配了两个域名www.ttyouni.com 和 ttyouni.com 在 ...

  8. 埃及分数-IDA*

    Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数.如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的.对于一个分数a/b, ...

  9. 调用jar程序,读取与jar同级的配置文件。

    System.getProperty("user.dir") + "\\Mysettings.properties";//该方法在Alimonitor里取不到绝 ...

  10. <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 的说明

    X-UA-Compatible是针对ie8新加的一个设置,对于ie8之外的浏览器是不识别的,这个区别与 content="IE=7"在无论页面是否包含<!DOCTYPE> ...