JS中的hook機(jī)制

hook機(jī)制也就是鉤子機(jī)制锅棕,由表驅(qū)動實現(xiàn)入撒,常用來處理多種特殊情況的處理。我們預(yù)定義了一些鉤子氯迂,在常用的代碼邏輯中去適配一些特殊的事件,這樣可以讓我們少些很多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]);
}

如果是用鉤子機(jī)制呢

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]);
}

所以簡單的說,其實鉤子機(jī)制就是利用一張表去匹配,而不是一次次的if條件判斷导帝。
jQuery中大量的使用了鉤子機(jī)制去做一些兼容守谓。拿$.type方法為例:

(function(window, undefined) {
    var
        // 用于預(yù)存儲一張類型表用于 hook
        class2type = {};
 
    // 原生的 typeof 方法并不能區(qū)分出一個變量它是 Array 、RegExp 等 object 類型舟扎,jQuery 為了擴(kuò)展 typeof 的表達(dá)力分飞,因此有了 $.type 方法
    // 針對一些特殊的對象(例如 null,Array睹限,RegExp)也進(jìn)行精準(zhǔn)的類型判斷
    // 運(yùn)用了鉤子機(jī)制譬猫,判斷類型前,將常見類型打表羡疗,先存于一個 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 對象的類型
        // 這個方法的關(guān)鍵之處在于 class2type[core_toString.call(obj)]
        // 可以使得 typeof obj 為 "object" 類型的得到更進(jìn)一步的精確判斷
        type: function(obj) {
 
            if (obj == null) {
                return String(obj);
            }
            // 利用事先存好的 hash 表 class2type 作精準(zhǔn)判斷
            // 這里因為 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;

這樣后邊就可以直接調(diào)用Object.prototype.toString()方法柳刮,而不用每次都再去原型鏈上去找,節(jié)約了很多開銷,jQuery中做了很多這樣的變量保存痒钝。
另外
typeof new Number(1) //= "object"這好像不科學(xué)啊——但是new出來的就是一個對象啊秉颗,顯然是我們的使用方式存在一些問題。應(yīng)該是按如下方法使用:

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

在這兒需要區(qū)別下兩個概念:對象實例和字面值送矩。
js中有5個基本數(shù)據(jù)類型:字符串蚕甥、數(shù)值、布爾類型栋荸、null和undefined菇怀。只有字符串、數(shù)值和布爾數(shù)據(jù)類型有對應(yīng)的構(gòu)造方法對象晌块。字符串爱沟、浮點數(shù)、整數(shù)和布爾值都是字面值匆背。

我們可以使用嚴(yán)格相等性來比較一個對象實例和一個字面值

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');
}

//打印結(jié)果
equal
equal
equal
not equal
not equal
not equal

也就是基本類型變量(沒有使用new創(chuàng)建的變量)嚴(yán)格的等于字面值呼伸,而對象實例則不會。
對于Object.prototype.toString方法更詳細(xì)的介紹,可以參考這篇博客


除了做一些兼容或者定值的匹配钝尸,鉤子機(jī)制在項目中能否使用呢蜂大?那我就做一個代碼的搬運(yùn)工,這是12年的一篇文章蝶怔,介紹鉤子機(jī)制在項目中的使用的 ,雖然這幾年面向?qū)ο蟮膶懛ㄔ诓粩嗟呢S富奶浦,不過,或許在某些方面我們?nèi)阅艿玫揭稽c借鑒吧踢星。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末澳叉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌成洗,老刑警劉巖五督,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瓶殃,居然都是意外死亡充包,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門遥椿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來基矮,“玉大人,你說我怎么就攤上這事冠场〖医剑” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵碴裙,是天一觀的道長钢悲。 經(jīng)常有香客問我,道長舔株,這世上最難降的妖魔是什么莺琳? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮载慈,結(jié)果婚禮上芦昔,老公的妹妹穿的比我還像新娘。我一直安慰自己娃肿,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布珠十。 她就那樣靜靜地躺著料扰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焙蹭。 梳的紋絲不亂的頭發(fā)上晒杈,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機(jī)與錄音孔厉,去河邊找鬼拯钻。 笑死,一個胖子當(dāng)著我的面吹牛撰豺,可吹牛的內(nèi)容都是我干的粪般。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼污桦,長吁一口氣:“原來是場噩夢啊……” “哼亩歹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤小作,失蹤者是張志新(化名)和其女友劉穎亭姥,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顾稀,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡达罗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了静秆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粮揉。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诡宗,靈堂內(nèi)的尸體忽然破棺而出滔蝉,到底是詐尸還是另有隱情,我是刑警寧澤塔沃,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布蝠引,位于F島的核電站,受9級特大地震影響蛀柴,放射性物質(zhì)發(fā)生泄漏螃概。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一鸽疾、第九天 我趴在偏房一處隱蔽的房頂上張望吊洼。 院中可真熱鬧,春花似錦制肮、人聲如沸冒窍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽综液。三九已至,卻和暖如春儒飒,著一層夾襖步出監(jiān)牢的瞬間谬莹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工桩了, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留附帽,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓井誉,卻偏偏與公主長得像蕉扮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颗圣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理慢显,服務(wù)發(fā)現(xiàn)爪模,斷路器,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法荚藻,類相關(guān)的語法屋灌,內(nèi)部類的語法,繼承相關(guān)的語法应狱,異常的語法共郭,線程的語...
    子非魚_t_閱讀 31,599評論 18 399
  • 其實呢這本書,有一個很深刻的名字.... 叫做《如何讓你愛的人愛上你》..... 但我決定換個優(yōu)雅的名字來匹配下我...
    微曉誒閱讀 403評論 0 2
  • 因為腳傷已經(jīng)刷了好幾部新劇疾呻,看了好多本書除嘹,而且因為有大把時間所以手止不住癢癢,寫了好幾篇七零八落的隨想岸蜗。然后忽然想...
    Ruby_6056閱讀 323評論 0 0
  • 這是致前任的一篇日記 提起前任璃岳,大家應(yīng)該都不會陌生年缎,前任對你來說是什么呢?是一段記憶铃慷,還是一段不可觸碰的傷痛单芜。對你...
    愛笑de小美閱讀 259評論 0 1