/*
 *
 *  [ js.hook.js ]
 *
 *  javascript钩子
 *
 *  * 劫持方法
 *  * 伪造参数
 *  * 篡改结果
 *  * 还原劫持
 *
 *  * 2016-10-25
 *  * vc1
 *
 */
hook('window.tool.calc').fakeArg('这个计算器坏了', -1).fakeRst('<(ˉ^ˉ)> 告诉你坏了');
window.hook()
传入需要hook的方法
- window下的方法可以直接使用hook(alert)的形式
- 对象中要劫持的方法使用字符串表示hook('window.object.fn')
.fakeArg()
修改传入原方法的参数
- 直接替换
- .fakeArg(参数1, 参数2, ..)原方法接收到的参数将以此为准
 
- 通过方法修改 - .fakeArg(function(原参数1, 原参数2, ..){
    /* 注:只修改上面的形参没啥大用 */
    arguments[0] = 'test';
    return arguments;
})
 - 
- 如果没有返回值会维持原来的参数不变
- 若要返回多个参数,使用数组
return [a, b, c]
- 返回空数组将清空所有参数值
 
.fakeRst()
修改原方法返回的参数
- 直接替换
- .fakeRst(参数1)众所周知js中只能返回一个值
 
- 通过方法修改 - .fakeRst(function(原返回值){
    /* 原方法返回值将以此为准 */
    return '修改之后实际返回的值'
})
 
.fake()
直接替换掉被hook的方法
``` 
.fake(function(args, data){
    /*
    args: 传入的arguments
    data: {
        fn_real,
        fn_name,
        fn_object_name,
        fn_object,
        get fn_puppet(),
        get fakeArgFn(),
        get fakeRstFn()
    }
    */
})
```
.off()
关闭劫持
- off('arg')停止fakeArg的劫持
- off('rst')停止fakeRst的劫持
- off()停止所有劫持,还原被劫持的方法
// 效果演示
window.tool = {
    say: '一个计算器开始工作了:',
    calc: function (msg, n) {
        console.log(this.say);
        console.warn('calc收到参数:' + msg + ', ' + n);
        var r = n * n;
        console.warn('calc结果:' + r);
        return r;
    }
}
console.clear();
console.info('一个计算器:');
console.group('原始方法:\n\ntool.calc');
console.log(tool.calc);
console.info('设置参数:' + '专注于计算平方的计算器' + ', ' + 42);
console.info('接收到的结果:' + tool.calc('专注于计算平方的计算器', 42));
console.groupEnd();
console.log('\n');
console.group("劫持后:\n\nhook('window.tool.calc').fakeArg('这个计算器坏了', -1).fakeRst('<(ˉ^ˉ)> 告诉你坏了');");
hook('window.tool.calc').fakeArg('这个计算器坏了', -1).fakeRst('<(ˉ^ˉ)> 告诉你坏了');
console.log(tool.calc);
console.info('设置参数:' + '专注于计算平方的计算器' + ', ' + 42);
console.info('接收到的结果:' + tool.calc('专注于计算平方的计算器', 42));
console.groupEnd();
console.log('\n');
console.group("还原后:\n\nhook('window.tool.calc').off();");
hook('window.tool.calc').off();
console.log(tool.calc);
console.info('设置参数:' + '专注于计算平方的计算器' + ', ' + 42);
console.info('接收到的结果:' + tool.calc('专注于计算平方的计算器', 42));
console.groupEnd();
console.log('\n');
console.group("替换:\n\nhook('window.tool.calc').fake(function(){...})");
hook('window.tool.calc').fake(function (args, data) {
    console.log('调用者:' + args.callee.caller);
    console.log('this:');
    console.log(this);
    console.log('args:');
    console.log(args);
    console.log('data:');
    console.log(data);
    return data.fn_real.apply({
        say: '怎么还是那个计算器:'
    }, args);
});
console.log(tool.calc);
console.info('设置参数:' + '专注于计算平方的计算器' + ', ' + 42);
console.info('接收到的结果:' + (function calc_caller() {
    return tool.calc.call({
        say: '换个计算器吧'
    }, '专注于计算平方的计算器', 42);
})());
console.groupEnd();
console.log('\n');

兼容ie8
