这个算是 Chrome only 其他的我没测试,也不想测试。因为我的控制台脚本仅仅在 Chrome 下加载。如果你需要全平台,那么这肯定不是你需要的结果。 需求其实我很早就想折腾这个了,但是,,因为懒,拖了很久,直到周末,我看到服务器上统计,发现流量翻了一倍,结果访问量还是一样的时候,我才下决心折腾。 知之为知之不知谷歌之一开始,谷歌一番,发现有两种思路。 第一个是 sindresorhus 大神写的 devtools-detect ,算是全平台兼容(除IE),但独立窗口打开的时候是检测不到的。 虽然有两个现成的,但这都不是我满意的模式,于是乎就有了本次 Chrome 控制台环境探索之旅。 分析控制台环境打开浏览器,按 F12 打开 console 后输入 debugger 按回车,然后按两次 F11,OK 完成。如果你的 Chrome 50 的话,映入眼帘的是密密麻麻的一大串压缩的字符,好在他们没 uglify,否则我就默默关了,也不会有这篇文章了。 点左下角 大致预览下代码,最终定位到 660 行的 // 用易懂的形式,描述各种对象方法,如正则,日期,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 可以检测控制台是否被打开了。 那么现在我们知道,其实完全可以借助 var re = /x/; var i = 0; re.toString = function () { return '第' + (i++) + '次打开控制台'; }; console.log(re); 简单又好用,也不需要定时器或resize事件监视,性能更是好的不用说。如果只是监听控制台打开,这个几行代码足以,但是我还没想到监听控制台关闭方法。 这么简单的代码,我就不写成插件装逼了,需要的时候直接用即可。 后序控制台环境下有很多功能都很方便很好用,多读读会发现很多神奇的技巧。 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|