Chrome 监听 console 打开

这个算是 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,035评论 25 707
  • chrome扩展开发入门教程 最近在开发chrome插件,看到一篇非常适合入门的教程,特记录一下 注:转载 本文首...
    谢大见阅读 6,430评论 1 25
  • 前言 Chrome浏览器我想是每一个前端er必用工具之一吧,一部分原因是它速度快,体积不大,支持的新特性也比其它浏...
    LiLi原上草阅读 1,282评论 0 0
  • 在做前端开发时,我们需要用到一些调试工具用来调试我们的HTML、CSS或者JS代码,俗话说预先善其事必先利其器,这...
    Rella7阅读 23,926评论 0 15
  • 阅读打卡第56天:今天读了,阿里巴巴和四十大盗,巴士拉银匠哈桑的故事,蠢汉,驴子与骗子。
    金凯乐麻麻阅读 88评论 0 0