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

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

    在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容—>异 ...

  2. c++函数重载

    为方便使用,在一定范围内,c++可以定义多个功能形似的同名函数,但是这些函数的形参必须不同(类型.个数.顺序),这就是重载函数.重载函数常用来实现功能类似而所处理的数据类型不同的问题. 看下面的一个例 ...

  3. [转]理解android.intent.category.LAUNCHER 具体作用

    转自:http://blog.csdn.net/jackrex/article/details/9189657 android.intent.category.LAUNCHER 具体有什么作用?我做一 ...

  4. Navicat(连接) -1之HTTP 设置

    HTTP 设置 HTTP 通道是一种连接到服务器的方法,使用与网络服务器相同的通讯协定(http://)和相同的端口(端口 80).这是当你的互联网服务供应商不允许直接连接,但允许创建 HTTP 连接 ...

  5. Win32API界面库 - Project wheels 工程基础部分完成

    离上次发博文过去了好久,先是要忙一个机器人的项目,然后就是部门的事情和考试周复习,然后就到了考试周,趁着复习的间隙,拾起了寒假时候抄的界面库,修掉了从前的bug. bug1 控件显示问题 当初抄这个库 ...

  6. JDK源码包结构分类

    最近查看JDK源码时,无意间发现几个类在陌生包里:com.sun.*.sun.*.org.*,google了一把总结了下以备他人搜索,如内容有误欢迎指正!   Jre库包含的jar文件(jdk1.6) ...

  7. day6_1

    一.加密模块 1.hashlib >>> data=hashlib.md5() >>> data.update(b'hello') >>> pri ...

  8. EXT学习之——Ext两个js之间的传参

    A  的js访问 B的js,并将A选择的guid的行传到  B的 js进行处理事项 A 的js 的写法var receiverFrom = new xxx.xxx子js方法体名 ({ parentCm ...

  9. 简单实用的Windows命令(一)

    前几天新买了一台笔记本电脑,使用了一下几个简单的查看电脑配置的命令,觉得非常的不错,在此记录一下 一:运行命令的方式有两种 1:使用快捷键WIN+R,然后在弹出的“运行”对话框中输入对应的命令 2:在 ...

  10. 10,SFDC 管理员篇 - 流程自动化

    1,Process Builder Setup | Build | Create | Workflow & Approvals | Process Builder 当我们在对象中创建或者修改一 ...