鈎子(HOOK)函數


什么是鈎子函數?

鈎子函數是Windows消息處理機制的一部分,通過設置“鈎子”,應用程序可以在系統級對所有消息、事件進行過濾,訪問在正常情況下無法訪問的消息。鈎子的本質是一段用以處理系統消息的程序,通過系統調用,把它掛入系統 --- 百度百科的定義

我的理解是:鈎子函數可以 鈎住 我喜歡的東西(在window中就是我喜歡的消息),這應該就是鈎子函數叫鈎子函數的原因吧。。?

鈎子函數的意義(用處)在於:我寫了一個window程序,在程序中我寫了一段代碼(調用window的api來實現鈎子),這段代碼被系統通過系統調用,把其掛入系統中,然后我就可以對我感興趣的消息進行處理,

我寫的這段代碼包含有一個回調函數,當有我喜歡的消息發出時,這個回調函數就會執行,所以說,鈎子就是指的回調函數

下面是一個程序掛載全局鈎子從而被360攔截的例子(其實360也有鈎子,不然怎么知道別人要掛載鈎子呢?即360可以攔截“掛載鈎子”的消息。這個彈窗就是在360的鈎子函數中創建的)

那么對於前端,什么是鈎子函數呢?

對於前端來說,鈎子函數就是指再所有函數執行前,我先執行了的函數,即 鈎住 我感興趣的函數,只要它執行,我就先執行。此概念(或者說現象)跟AOP(面向切面編程)很像

一個鈎子函數的例子

 1 function Hooks(){
 2     return {
 3         initEnv:function () {
 4             Function.prototype.hook = function (realFunc,hookFunc,context,funcName) {
 5                 var _context = null; //函數上下文
 6                 var _funcName = null; //函數名
 7 
 8                 _context = context || window;
 9                 _funcName = funcName || getFuncName(this);
10                 _context[realFunc] = this;
11 
12                 if(_context[_funcName].prototype && _context[_funcName].prototype.isHooked){
13                     console.log("Already has been hooked,unhook first");
14                     return false;
15                 }
16                 function getFuncName (fn) {
17                     // 獲取函數名
18                     var strFunc = fn.toString();
19                     var _regex = /function\s+(\w+)\s*\(/;
20                     var patten = strFunc.match(_regex);
21                     if (patten) {
22                         return patten[1];
23                     };
24                     return '';
25                 }
26                 try{
27                     eval('_context[_funcName] = function '+_funcName+'(){\n'+
28                         'var args = Array.prototype.slice.call(arguments,0);\n'+
29                         'var obj = this;\n'+
30                         'hookFunc.apply(obj,args)\n'+
31                         'return _context[realFunc].apply(obj,args);\n'+
32                         '};');
33                     _context[_funcName].prototype.isHooked = true;
34                     return true;
35                 }catch (e){
36                     console.log("Hook failed,check the params.");
37                     return false;
38                 }
39             }
40             Function.prototype.unhook = function (realFunc,funcName,context) {
41                 var _context = null;
42                 var _funcName = null;
43                 _context = context || window;
44                 _funcName = funcName;
45                 if (!_context[_funcName].prototype.isHooked)
46                 {
47                     console.log("No function is hooked on");
48                     return false;
49                 }
50                 _context[_funcName] = _context[realFunc];
51                 delete _context[realFunc];
52                 return true;
53             }
54         },
55         cleanEnv:function () {
56             if(Function.prototype.hasOwnProperty("hook")){
57                 delete Function.prototype.hook;
58             }
59             if(Function.prototype.hasOwnProperty("unhook")){
60                 delete Function.prototype.unhook;
61             }
62             return true;
63         }
64     };
65 }
66 
67 var hook = Hooks();
68 hook.initEnv();
69 
70 // 這個是要執行的正常的函數
71 function test(){
72     alert('test');
73 }
74 
75 // 這個是鈎子函數。此鈎子函數內心戲:
76 // 我只喜歡test函數,所以我必須出現在她前面(在她前面執行),這樣她才能看到我。
77 function hookFunc(){
78     alert('hookFunc');
79 }
80 
81 // hookFunc鈎住test
82 test.hook(test,hookFunc,window,"test");
83 
84 window.onload = function(){
85   // 由於鈎子函數hookFunc鈎住了test函數,所以test執行時,會先執行hookFunc。
86   test();
87 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM