资讯专栏INFORMATION COLUMN

从函数劫持角度看开发调试工具AlloyLever

xiongzenghui / 3012人阅读

摘要:第四行是为了保存当前语境下的,事实上在浏览器的调试工具中直接运行这些代码的时候,这个指向的就是全局对象,所以去掉这一行,将下面的改成,程序的运行结果是一模一样的。

在腾讯的AlloyTeam的Blog上发现了这样的一款工具:AlloyLever(原blog地址:http://www.alloyteam.com/2016...),觉得非常有趣且实用。尤其是其实现的原理也并不复杂,却可以给平常的调试工作带来巨大的便利,不得不让人感叹凡事就怕认真啊。

这个就是这款工具的样子,它整合了web调试中几个非常频繁的刚需:看log、看error、看AJAX发包与回包。同时还附有查看timeline、cookie和localStorage的这些功能。虽然这些信息在chrome的调试工具里面也是触手可及,可是由于涉及的原因,他们被放在跟原web页面不相关的一个窗口里,还分了很多的标签页,在实际工作中,一个web页面+F12的调试窗口经常就占满了整个屏幕,着实是有些不太方便。这也是这个工具最初被制造出来,想要解决的问题吧。

这个工具的实现原理,是很简单的函数劫持。有关于函数劫持的相关知识,可参见这篇文章(https://segmentfault.com/a/11...),其大概原理是创建一个和现有函数同名的函数(当然首先要把原来的函数给保存下来),以覆盖掉他原本的引用,然后在函数体内先针对参数做一些自己想要实现的功能,最后再调用之前保存的原函数,实现原本的功能。
这个思路也很像redux里面有关于middleware的设计,只不过redux运用的思想更为先进,通过一系列结构将各个中间件解耦,互不干扰。而本文的目的不是为了灵活的使用各种中间件,只是为了想做一个调试信息的自主整合页面,所以使用这种强联系的耦合方式也没有什么大问题。

原文中的关键源码如下:

window.console = {
    wc: window.console
};    //将原本console的引用指向console的一个成员变量wc,以便在后面扩充的函数中使用。
var self = this;  //保存当前语境中的this
["log", "error", "warn", "debug", "info"].forEach(function (item) {  //针对console的五种方法
    console[item] = function (msg) {
        this.wc[item](msg);
        self.log(msg, item);
    }
});

代码选自原网页,注释是我加的。

在JavaScript中,函数也是对象的一种,也能像对象一样拥有自己的变量。所以程序的前三行就是讲console这个对象换了一个别名wc保存在console本身内。
第四行是为了保存当前语境下的this,事实上在浏览器的调试工具中直接运行这些代码的时候,这个this指向的就是全局对象window,所以去掉这一行,将下面的self.log改成window.log,程序的运行结果是一模一样的。
保存完了所有需要的变量后,下面的事情就简单了,遍历console下的log, error, warn, debug和info这五个方法,把他们都修改成先执行本身,然后再执行我们自定义的log方法,在这个自定义的log方法内,我们能访问到传入的参数msg和访问的原生函数名item,然后就可以通过这个钩子,去获取数据,并做一些处理,显示到AlloyLever的控制台上啦。

而ajax的截获跟这个原理也差不多,代码如下:

var XHR = window.XMLHttpRequest;
 
window.XMLHttpRequest=function(){
    var xhr = new XHR();
    checkSuccess(xhr);
    return xhr;
};
 
window.XMLHttpRequest.realXHR = XHR;
 
var self=this;
 
function checkSuccess(xhr) {
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
        self.option.xhrs.push({url:xhr.responseURL, json:JSON.stringify(JSON.parse( xhr.responseText), null, "	")})
    }else if(xhr.status>=400) {
        console.error(xhr.responseURL +" "+xhr.status+" ("+xhr.statusText+")")
    }
    else{
        window.setTimeout(function () {
            checkSuccess(xhr);
        }, 0);
    }
}

区别就是因为ajax是异步请求,所以在函数内部内置了一个setTimeout循环,如果请求未完成则一直循环,直到请求完成,内容被捕获为止。

这个工具还有个移动端的版本:https://github.com/WechatFE/v...
对于做微信开发的小伙伴们,以后的测试就方便多啦!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91248.html

相关文章

  • 前端常用插件、工具类库汇总

    摘要:页面调试腾讯开发维护的代码调试发布,错误监控上报,用户问题定位。同样是由腾讯开发维护的代码调试工具,是针对移动端的调试工具。前端业务代码工具库。动画库动画库,也是目前通用的动画库。 本人微信公众号:前端修炼之路,欢迎关注 本篇文章整理自己使用过的和看到过的一些插件和工具,方便日后自己查找和使用。 另外,感谢白小明,文中很多的工具来源于此。 弹出框 layer:http://layer....

    GitCafe 评论0 收藏0
  • 一名【合格】前端工程师的自检清单

    摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。 开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研...

    罗志环 评论0 收藏0
  • 一名【合格】前端工程师的自检清单

    摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研发体系...

    isaced 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<