这个算是 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. Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext

    上一主题(查看)中,了解了IOC容器的基本概念,以及BeanFactory的设计与实现方式,这里就来了解一下ApplicationContext方式的实现. ApplicationContext 在S ...

  2. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作

    http://www.cnblogs.com/wgp13x/p/4934521.html 内容一样,样式好的版本. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据 ...

  3. [转]输出带颜色的shell

    格式: echo -e "\033[字背景颜色;字体颜色m字符串\033[0m" 例如: echo -e "\033[41;36m something here \033 ...

  4. docker-7 docker在阿里云的使用

    在传统模式中,开发团队在开发环境中完成软件开发,自己做了一遍单元测试, 测试通过,ᨀ交到代码版本管理库.运维把应用部署到测 试环境, QA 进行测试,没问题后通知部署人员发布到生产环境. 在上述过程中 ...

  5. addrinfo 结构

    typedef struct addrinfo {int             ai_flags;int            ai_family;int             ai_sockty ...

  6. linux基础-第七单元 用户、群组及权限的深入讨论

    怎样查看文件的权限 ls命令详解 root用户及文件的安全控制 什么是root用户 用户分类 文件操作权限 文件操作权限的字符表示 chown chgrp 使用符号表示法设定文件或目录上的权限 chm ...

  7. 浅谈输入输出”重定向“——基于Linux系统

    前言 进程在启动后会自动的打开3个文件:标准输入.标准输出和标准错误输出分别对应文件描述符0.1.2.对于每个进程他们都都维护了一张文件描述符表(file descriptor table),通常fd ...

  8. 小菜学Chromium之OpenGL学习之二

    在这个教程里,我们一起来玩第一个OpenGL程序.它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出.它是我们以后应用程序的框架. 在CodeBlock里创建一个新的GLUT ...

  9. hadoop日常运维与升级总结

    日常运维 升级 问题处理方法 日常运维 进程管理 由于配置文件的更改,需要重启生效, 或者是进程自己因某种致命原因终止, 或者发现进程工作出现异常等情况下,需要进行手动进程的关闭或启动, 或者是增删节 ...

  10. 我懒蛋又回来了!-PDO

    hi 好几天了吧,脚伤都有一周了的.玩乐的这么久才发觉,对于年轻人,或者更具体的,对我而言,受伤最难受的不是受伤瞬间的身痛,不是随之而来的心理负担,不是独自一人远在他乡的孤独无助之感:最伤的是斗志,是 ...