zoukankan      html  css  js  c++  java
  • 【repost】JS中的hook机制

    hook机制也就是钩子机制,由表驱动实现,常用来处理多种特殊情况的处理。我们预定义了一些钩子,在常用的代码逻辑中去适配一些特殊的事件,这样可以让我们少些很多if else语句。
    举个高考加分的例子,比如获得过全国一等奖加20分,二等奖加10分,三等奖加5分。使用if else的话:

    function student(name,score,praise){
        return {
            name:name,
            score:score,
            praise:praise
        }
    }
    function praiseAdd(students){
        var results={};
        for (var i in students){
            var curStudent=students[i];
            var ret=curStudent.score;
            if(curStudent.praise==1){
                ret+=20;
            }else if(curStudent.praise==2){
                ret+=10;
            }else if(curStudent.praise==3){
                ret+=5;
            }
            results[curStudent.name]=ret;
        } 
        return results;
    
    }
    var liming= student("liming",70,1);
    var liyi= student("liyi",90,2);
    var liuwei= student("liuwei",80,3);
    var ertuzi= student("ertuzi",85,3);
    
    var result=praiseAdd([liming,liyi,liuwei,ertuzi]);
    for(var i in result){
        console.log("name:"+i+",score:"+result[i]);
    }

    如果是用钩子机制呢

    function student(name,score,praise){
        return {
            name:name,
            score:score,
            praise:praise
        }
    }
    var  praiseList={
        1:20,
        2:10,
        3:5
    } 
    function praiseAdd(students){
        var results={};
        for (var i in students){
            var curStudent=students[i];
            var ret=curStudent.score;
            if(praiseList[curStudent.praise])
            ret+=praiseList[curStudent.praise];
            results[curStudent.name] = ret;
        } 
        return results;
    
    }
    var liming= student("liming",70,1);
    var liyi= student("liyi",90,2);
    var liuwei= student("liuwei",80,3);
    var ertuzi= student("ertuzi",85,3);
    
    var result=praiseAdd([liming,liyi,liuwei,ertuzi]);
    for(var i in result){
        console.log("name:"+i+",score:"+result[i]);
    }

    所以简单的说,其实钩子机制就是利用一张表去匹配,而不是一次次的if条件判断。
    jQuery中大量的使用了钩子机制去做一些兼容。拿$.type方法为例:

    (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);

    core_toString是定义了一个空对象,然后保存toString()方法。

    var core={};
    var core_toString=core.toString;

    这样后边就可以直接调用Object.prototype.toString()方法,而不用每次都再去原型链上去找,节约了很多开销,jQuery中做了很多这样的变量保存。
    另外
    typeof new Number(1) //= "object"这好像不科学啊——但是new出来的就是一个对象啊,显然是我们的使用方式存在一些问题。应该是按如下方法使用:

    Object.prototype.toString.call(new Number(1))         //= "[object Number]"

    在这儿需要区别下两个概念:对象实例和字面值。
    js中有5个基本数据类型:字符串、数值、布尔类型、null和undefined。只有字符串、数值和布尔数据类型有对应的构造方法对象。字符串、浮点数、整数和布尔值都是字面值。

    我们可以使用严格相等性来比较一个对象实例和一个字面值

    var str1 = String("string");
    var num1 = Number(1.23);
    var bool1 = Boolean(true);
    
    if (str1 === "string") {
        console.log("equal");
    }
    if (num1 === 1.23) {
        console.log('equal');
    }
    if (bool1 === true) {
        console.log('equal');
    }
    
    var str2 = new String("string");
    var num2 = new Number(1.23);
    var bool2 = new Boolean(true);
    
    if (str2 === "string") {
        console.log('equal');
    } else {
        console.log('not equal');
    }
    if (num2 === 1.23) {
        console.log('equal');
    } else {
        console.log('not equal');
    }
    if (bool2 === true) {
        console.log('equal');
    } else {
        console.log('not equal');
    }
    
    //打印结果
    equal
    equal
    equal
    not equal
    not equal
    not equal

    也就是基本类型变量(没有使用new创建的变量)严格的等于字面值,而对象实例则不会。
    对于Object.prototype.toString方法更详细的介绍,可以参考这篇博客


    除了做一些兼容或者定值的匹配,钩子机制在项目中能否使用呢?那我就做一个代码的搬运工,这是12年的一篇文章,介绍钩子机制在项目中的使用的 ,虽然这几年面向对象的写法在不断的丰富,不过,或许在某些方面我们仍能得到一点借鉴吧。

  • 相关阅读:
    POJMatrix(二维树状数组)
    HD1556Color the ball(树状数组)
    闲的没事,自挂东南枝
    高端、洋气效果
    “绝对”妹纸~position
    float元素一定要闭合
    dw cs6激活码一枚
    shell 预定义变量
    ubuntu 安装docker
    Microsonf visual c++ 14+ 离线内网安装
  • 原文地址:https://www.cnblogs.com/neil080320/p/6287383.html
Copyright © 2011-2022 走看看