浏览器判断控制台是否开启

78 阅读2分钟

根据 console.table 的执行时长

这种方案还是可以的,BOSS 用的这个。

function checkIsOpen() {
    const bengin = new Date().valueOf();
    console.table(new Array(100).fill(1).map(item => new Array(100).fill(1)))
    const end = new Date().valueOf();
    console.clear();
    return (end - bengin) > 5
}
console.log(checkIsOpen())

toString 检测 (已经没有用了)

这个方案,是基于console.log不会在控制台开启时执行的前提条件下才会生效,但是目前浏览器这个不行。

function checkIsOpen() {
    
}
checkIsOpen.toString = function() {
    this.isOpen = true;
}
console.log(checkIsOpen)

这个方案已经无了,但是可以了解一下console.log。 console.log() API ‌无论 DevTools 是否打开都会执行‌,但其行为和影响在不同状态下有显著差异。

性能与内存影响不同‌:

  • DevTools 关闭时‌:
    日志输出通常由浏览器轻量处理,‌不会导致内存泄漏‌,堆内存保持稳定。
  • DevTools 打开时‌:
    浏览器会‌保留被打印对象的引用‌(尤其是对象/数组),以便在控制台中展开查看,这可能导致‌内存无法被垃圾回收(GC) ‌,从而引发内存泄漏。nodejs 环境不会内存泄漏

监控debugger

function checkIsOpen() {
    const bengin = new Date().valueOf();
    debugger;
    const end = new Date().valueOf();
    console.clear();
    return (end - bengin) > 5
}
console.log(checkIsOpen())

就是利用断点。

DOM元素检测

就是挂一个隐藏的 html 标签放页面上监控这个 html 标签的offsetHeightoffsetWidth。 这个也无了。

伪造一个看着合法的 Event

...
<body>
    <button id="app">click me</button>
    <button id="trigger">触发按钮</button>
</body>

<script>
    function withTrustedTrue(event) {
        // 代理 event;除 isTrusted 外可按需扩展其它 key 的拦截
        // 比如添加 pageX, pageY, offsetX, offsetY, clientX, clientY, screenX, screenY 等坐标
        // 添加  target currentTarget 等属性
        return new Proxy(event, {
            get(target, prop) {
                if (prop === 'isTrusted') return true;
                return Reflect.get(target, prop, target);
            },
        });
    }

    function wrapEventListener(handler) {
        return function wrappedDomListener() {
            const event = arguments[0];
            if (event.isTrusted) return handler.apply(this, arguments);
            try {
                arguments[0] = withTrustedTrue(event);
                return handler.apply(this, arguments);
            } catch (err) {
                console.log(err);
            }
        };
    }

    function patchedAddEventListener(type, handler, options) {
        this.originalAddEventListener(type, wrapEventListener(handler), options);
    }
    
    patchedAddEventListener.toString = function() {
        return "function addEventListener() { [native code] }"
    }
    
    for (const ctor of [EventTarget, Document]) {
        ctor.prototype.originalAddEventListener = ctor.prototype.addEventListener;
        ctor.prototype.addEventListener = patchedAddEventListener;
    }

    const appElement = document.querySelector("#app");
    appElement.addEventListener("click", function () {
        const event = arguments[0];
        for (let key in event) {
            console.log(key, event[key]);
        }
    });

    const triggerElement = document.querySelector("#trigger");
    triggerElement.addEventListener("click", function () {
        const event = new Event("click");
        appElement.dispatchEvent(event);
    });
</script>
...