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借鑒吧踢星。