这个算是 Chrome only 其他的我没测试,也不想测试。因为我的控制台脚本仅仅在 Chrome 下加载。

如果你需要全平台,那么这肯定不是你需要的结果。

需求

其实我很早就想折腾这个了,但是,,因为懒,拖了很久,直到周末,我看到服务器上统计,发现流量翻了一倍,结果访问量还是一样的时候,我才下决心折腾。

知之为知之不知谷歌之

一开始,谷歌一番,发现有两种思路。

第一个是 sindresorhus 大神写的 devtools-detect,算是全平台兼容(除IE),但独立窗口打开的时候是检测不到的。

另一个是咱们国人 zswang 写的 jdetects,目测也是 Chrome only,当然我的灵感也来至于他。

虽然有两个现成的,但这都不是我满意的模式,于是乎就有了本次 Chrome 控制台环境探索之旅。

分析控制台环境

根据 zswangjdetects 得知,控制台会解析节点元素的 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 打开的更多相关文章

  1. javascript 反调试 监听用户打开了Chrome devtool

    let div = document.createElement('div'); let loop = setInterval(() => {     console.log(div);     ...

  2. [Android Pro] 监听WIFI 打开广播

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-perm ...

  3. android监听屏幕打开关闭广播无响应的情况

    android在屏幕打开和关闭的时候会发出广播,但是如果receiver配置在AndroidManifest.xml中时,receiver是接受不到任何广播的. <receiver androi ...

  4. 如何实现监听 console.log

    var lastLog; console.oldLog = console.log; console.log = function(str) { console.oldLog(str); lastLo ...

  5. chrome 监听touch类事件报错:无法被动侦听事件preventDefault

    先上错误信息: Unable to preventDefault inside passive event listener due to target being treated as passiv ...

  6. [Android Pro] 监听Blutooth打开广播

    <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission a ...

  7. Android onclick监听事件打开新界面

    一.新建工程 二.新建XML代码 新建一个Button <Button android:layout_width="wrap_content" android:layout_ ...

  8. oracle 监听服务OracleOraDb11g_home1TNSListener打开后立马停止错误

    首先我真得吐槽一下,我安装这个破软件感觉真的是把能遇到的错误都遇到一遍了,生气!!!!!!! 关于监听服务OracleOraDb11g_home1TNSListener打开后立马停止这个错误,我的解决 ...

  9. 连接linux数据库Oracle时报错ORA-12541: TNS: 无监听程序

    远程服务器的数据库服务未开启,以及监听未打开 连接oracle 启动服务,startup 切换到oracle /bin 目录,cd $ORACLE_HOME/bin 启动监听, lsnrctl sta ...

随机推荐

  1. ORACLE数据库对比表结构

    有时候会有某种需求:需要对比两个表的表结构是否一致,有时候甚至是整个数据库所有表的表结构对比.......表结构对比无非就是字段名.字段类型.字段数据类型.以及字段的顺序的对比.如果需要对比表结构,可 ...

  2. mysql源码解读之配置文件

    要研究mysql,最好的资源莫过于源码了,所以本人打算通过调试源码的方式来深入理解mysql的点点滴滴.搭建mysql调试环境很简单,从官方下载mysql源码,利用cmake工具生成工程即可.为了方便 ...

  3. Java NIO 同步非阻塞

    同步非阻塞IO (NIO) NIO是基于事件驱动思想的,实现上通常采用Reactor(http://en.wikipedia.org/wiki/Reactor_pattern)模式,从程序角度而言,当 ...

  4. 烂泥:使用snmpwalk采集设备的OID信息

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 打算开始学习有关监控方面的知识,但是现在很多监控系统都是根据SNMP进行的.而SNMP监控的性能指标很多都是通过snmpwalk采集设备的OID信息得到 ...

  5. Jmeter之Bean shell使用(二)

    上一篇Jmeter之Bean shell使用(一)简单介绍了下Jmeter中的Bean shell,本文是对上文的一个补充,主要总结下常用的几种场景和方法,相信这些基本可以涵盖大部分的需求.本节内容如 ...

  6. andriod 动态设置TextView 和 RelativeLayou 高度

    XML布局 <RelativeLayout android:id="@+id/rlay_meeting_contact_context" android:layout_wid ...

  7. 磁盘配额-----quota

    为什么要使用磁盘配额:为了限制普通用户使用普通磁盘的空间与创建文件的个数等. 不至于个别人的浪费影响所有人的使用. 需要安装quota的软件包. mount -o usrquota,grpquota ...

  8. MySQL Database on Azure

    在国际版的Microsoft Azure上,MySQL服务是与ClearDB合作运营的.由于ClearDB无法在中国地区提供服务,因此微软中国的研发团队开发了专门面向中国市场的MySQL Databa ...

  9. css3中变形与动画(二)

    css3制作动画的几个属性:变形(transform),过渡(transition)和动画(animation). transform介绍过了.接下来介绍过渡transition. 一.例子 先通过一 ...

  10. html5新增及删除标签

    一.新增标签 有一种划分为,功能性标签[html5新增,如canvas,旧浏览器没有]和语义性标签[如header等只是增强语义,没有新功能].下面按照分几个小类来说. 1.结构标签 新增的结构标签, ...