JS钩子示例

// JS钩子示例
// JS对于不同消息类型,实现了不同的调用链
// 事件触发的时候,根据消息类型,调用对应的调用链
// 同一个钩子函数,安装多次,会根据安装顺序,调用多次
// 可以对比Windows API的钩子如SetWindowsHookEx等,原理上很相似

// 储存全部事件的调用链函数列表
function hooks() {
    this.queue = new Array();
}

// 通过addAction,生成调用链
hooks.prototype.addAction = function (hook, func) {
    // 某一个事件的调用链函数列表
    if(this.queue[hook]==undefined){
        this.queue[hook] = new Array(); 
    }
    
    if (typeof func == 'function') {
        this.queue[hook].push(func);
    } else if (typeof func == 'string') {
        this.queue[hook].push(this.window[func]);
    }
}

// 通过doAction,实现调用链
hooks.prototype.doAction = function (hook) {
    var parameters = Array.prototype.slice.call(arguments, 1); 
    var functions = this.queue[hook]; 
    for (var i = 0; i < functions.length; i++) {
        this.call_user_func_array(functions[i], parameters);
    }
    return true;
}

// 实现具体钩子函数调用
hooks.prototype.call_user_func_array = function(cb, parameters) {
    if (typeof cb === 'string') {
        func = (typeof this[cb] === 'function') ? this[cb] : func = (newFunction(null, 'return ' + cb))();
    } else if (cb instanceof Array) {
        func = (typeof cb[0] == 'string') ? eval(cb[0] + "['" + cb[1] + "']") : func = cb[0][cb[1]];
    } else if (typeof cb === 'function') {
        func = cb;
    } if (typeof func != 'function') {
        throw new Error(func + ' is not a valid function');
    } if (typeof parameters == 'undefined') {
        var tmp_ary = [];
        var parameters = Array.prototype.slice.call(tmp_ary, 1);
    } return (typeof cb[0] === 'string') ? func.apply(eval(cb[0]), parameters) : (typeof cb[0] !== 'object') ? func.apply(null, parameters) : func.apply(cb[0], parameters);
}

function func1() {
    console.log("func1");
}

function func2() {
    console.log("func2");
}

function func3() {
    console.log("func3");
}

// 使用示例
var myhook = new hooks();
myhook.addAction("loaded", func3);
myhook.addAction("loaded", func2);
myhook.addAction("loaded", func1);
myhook.addAction("loaded", func3);
myhook.doAction("loaded")