Chrome 监听 console 打开
这个算是 Chrome only 其他的我没测试,也不想测试。因为我的控制台脚本仅仅在 Chrome 下加载。
如果你需要全平台,那么这肯定不是你需要的结果。
需求
其实我很早就想折腾这个了,但是,,因为懒,拖了很久,直到周末,我看到服务器上统计,发现流量翻了一倍,结果访问量还是一样的时候,我才下决心折腾。
知之为知之不知谷歌之
一开始,谷歌一番,发现有两种思路。
第一个是 sindresorhus 大神写的 devtools-detect,算是全平台兼容(除IE),但独立窗口打开的时候是检测不到的。
另一个是咱们国人 zswang 写的 jdetects,目测也是 Chrome only,当然我的灵感也来至于他。
虽然有两个现成的,但这都不是我满意的模式,于是乎就有了本次 Chrome 控制台环境探索之旅。
分析控制台环境
根据 zswang 的 jdetects 得知,控制台会解析节点元素的 id 属性。
那么为什么会解析呢?或者他还做了什么处理呢?
打开浏览器,按 F12 打开 console 后输入 debugger 按回车,然后按两次 F11,OK 完成。
如果你的 Chrome 50 的话,映入眼帘的是密密麻麻的一大串压缩的字符,好在他们没 uglify,否则我就默默关了,也不会有这篇文章了。
点左下角 {} 格式化代码后,变的非常漂亮,但是没有注释了,我记得之前版本都是有注释的,更容易阅读。
大致预览下代码,最终定位到 660 行的 _describe 方法处,其他都不管我也不知道干嘛的,分析需要的代码即可。
// 用易懂的形式,描述各种对象方法,如正则,日期,node,数组,函数 等。
_describe: function(obj) {
if (this.isPrimitiveValue(obj)) // 如果是原始值不描述
return null;
// 获取类型名包括 ArrayLike,但不是 Object.prototype.toString,有兴趣可以单独查看源码
var subtype = this._subtype(obj);
if (subtype === "regexp") // 正则和日期输出 toString 后的结果。
return toString(obj);
if (subtype === "date")
return toString(obj);
if (subtype === "node") { // dom 节点处理,这里是重点
// 获取节点名,text comment 等只有 nodeName
var description = obj.nodeName.toLowerCase();
switch (obj.nodeType) { // 节点类型
case 1: // Element 类型
description += obj.id ? "#" + obj.id : ""; // 获取元素 id
var className = obj.className; // 获取元素 class
description += (className && typeof className === "string") ? "." + className.trim().replace(/\s+/g, ".") : "";
break;
case 10: // DocumentType 类型
description = "<!DOCTYPE " + description + ">";
break;
}
return description;
}
// 获取内部构造函数名,可能类似 Object.prototype.toString
var className = InjectedScriptHost.internalConstructorName(obj);
// 类似数组的就输出 对象名[长度] 比如 Array[3], jQuery.fn.jQuery.init[2] 之类的
if (subtype === "array") {
if (typeof obj.length === "number")
className += "[" + obj.length + "]";
return className;
}
if (typeof obj === "function") // 函数 toString
return toString(obj);
if (isSymbol(obj)) { // Symbol 处理
try {
return (InjectedScriptHost.callFunction(Symbol.prototype.toString, obj)) || "Symbol";
} catch (e) {
return "Symbol";
}
}
// 错误类型处理
if (InjectedScriptHost.subtype(obj) === "error") {
try {
var stack = obj.stack;
var message = obj.message && obj.message.length ? ": " + obj.message : "";
var firstCallFrame = /^\s+at\s/m.exec(stack);
var stackMessageEnd = firstCallFrame ? firstCallFrame.index : -1;
if (stackMessageEnd !== -1) {
var stackTrace = stack.substr(stackMessageEnd);
return className + message + "\n" + stackTrace;
}
return className + message;
} catch (e) {}
}
return className;
}
OK,代码挺简单的,看完基本就知道为什么 jdetects 可以检测控制台是否被打开了。
那么现在我们知道,其实完全可以借助 正则,日期,函数 的 toString 实现,而且更简单,例如:
var re = /x/;
var i = 0;
console.log(re);
re.toString = function () {
return '第 ' + (++i) + ' 次打开控制台';
};
简单又好用,也不需要定时器或 resize 事件监视,性能更是好到不用说。需要注意的是这里的 re.toString 必须在 console.log 之后定义,否则没打开控制台 toString 也会执行。
如果只是监听控制台打开,这个几行代码足以,但是我还没想到监听控制台关闭方法。
这么简单的代码,我就不写成插件装逼了,需要的时候直接用即可。在 runjs 上写了个 demo,打开预览下效果吧!
预览: http://sandbox.runjs.cn/show/vjtgjbzg
后序
控制台环境下有很多功能都很方便很好用,多读读会发现很多神奇的技巧。
本文同步至我的个人博客:http://www.52cik.com/2016/04/27/chrome-console-open.html
Chrome 监听 console 打开的更多相关文章
- javascript 反调试 监听用户打开了Chrome devtool
let div = document.createElement('div'); let loop = setInterval(() => { console.log(div); ...
- [Android Pro] 监听WIFI 打开广播
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-perm ...
- android监听屏幕打开关闭广播无响应的情况
android在屏幕打开和关闭的时候会发出广播,但是如果receiver配置在AndroidManifest.xml中时,receiver是接受不到任何广播的. <receiver androi ...
- 如何实现监听 console.log
var lastLog; console.oldLog = console.log; console.log = function(str) { console.oldLog(str); lastLo ...
- chrome 监听touch类事件报错:无法被动侦听事件preventDefault
先上错误信息: Unable to preventDefault inside passive event listener due to target being treated as passiv ...
- [Android Pro] 监听Blutooth打开广播
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission a ...
- Android onclick监听事件打开新界面
一.新建工程 二.新建XML代码 新建一个Button <Button android:layout_width="wrap_content" android:layout_ ...
- oracle 监听服务OracleOraDb11g_home1TNSListener打开后立马停止错误
首先我真得吐槽一下,我安装这个破软件感觉真的是把能遇到的错误都遇到一遍了,生气!!!!!!! 关于监听服务OracleOraDb11g_home1TNSListener打开后立马停止这个错误,我的解决 ...
- 连接linux数据库Oracle时报错ORA-12541: TNS: 无监听程序
远程服务器的数据库服务未开启,以及监听未打开 连接oracle 启动服务,startup 切换到oracle /bin 目录,cd $ORACLE_HOME/bin 启动监听, lsnrctl sta ...
随机推荐
- 查看mysql,apache,php,nginx编译参数
查看nginx编译参数: #/usr/local/nginx/sbin/nginx -V 查看mysql编译参数: cat /usr/local/mysql/bin/mysqlbug | grep ...
- WebApi深入学习--概述+路由查找
如何创建Controller这里就不说了,只写一些可能是高阶知识的内容 关于WebApi的官方介绍及示例 http://www.asp.net/web-api/ 1.跨域 Asp.NET有专门的跨域扩 ...
- 知方可补不足~sqlserver中对xml类型字段的操作
回到目录 在sqlserver中有很多种数据类型,而XML数据类型是比较新奇怪的一种格式,我们平常接触的可能比较少,用的也少,而在某些场合,使用XML类型可能会使我们的开发变简单,下面就是一种情况: ...
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- Linux软件安装-RPM安装
RPM是RPM Package Manager(RPM软件包管理器)的缩写,这一文件格式名称虽然打上了RedHat的标志,但是其原始设计理念是开放式的,现在包括OpenLinux. S ...
- HDU3535AreYouBusy[混合背包 分组背包]
AreYouBusy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HTML5 WebSocket 技术介绍
WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这 ...
- 关于数组的map、reduce、filter
map:map()方法定义在Array中,传入自己的参数,就得到一个新的Array作为结果 var aqiData = [ ["北京", 90], ["上海", ...
- hdu 1542 & & poj 1151
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- Android保存ArrayList至SharedPreferences
保存ArrayList至SharedPreferences 其中ArrayList中每个元素为String List<String> environmentList = new Array ...