簡體   English   中英

在 Chrome 中攔截對 console.log 的調用

[英]Intercept calls to console.log in Chrome

我有一個無法更改的腳本,它會進行大量console.log調用。 如果調用包含某些字符串,我想添加另一個層並做出響應。 這在 Firefox 中有效,但在 Chrome 中的第 4 行引發“ Illegal invocation ”錯誤:

var oldConsole = {};
oldConsole.log = console.log;
console.log = function (arg) {
    oldConsole.log('MY CONSOLE!!');
    oldConsole.log(arg);
}

任何想法如何解決這個問題? 我也嘗試克隆控制台...

您需要在 chrome 的console上下文中調用console.log

(function () {
  var log = console.log;
  console.log = function () {
    log.call(this, 'My Console!!!');
    log.apply(this, Array.prototype.slice.call(arguments));
  };
}());

現代語言功能可以顯着簡化此代碼段:

{
  const log = console.log.bind(console)
  console.log = (...args) => {
    log('My Console!!!')
    log(...args)
  }
}

我知道這是一篇舊帖子,但無論如何它都會很有用,因為其他解決方案與舊瀏覽器不兼容。

您可以像這樣重新定義控制台(以及所有瀏覽器)的每個功能的行為:

// define a new console
var console = (function(oldCons){
    return {
        log: function(text){
            oldCons.log(text);
            // Your code
        },
        info: function (text) {
            oldCons.info(text);
            // Your code
        },
        warn: function (text) {
            oldCons.warn(text);
            // Your code
        },
        error: function (text) {
            oldCons.error(text);
            // Your code
        }
    };
}(window.console));

//Then redefine the old console
window.console = console;

您也可以使用相同的邏輯,但在控制台對象中調用它,因此上下文是相同的。

if(window.console){
  console.yo = console.log;
  console.log = function(str){
    console.yo('MY CONSOLE!!');
    console.yo(str);
  }
}

使用 ES6 新的擴展運算符,您可以這樣編寫

(function () {
  var log = console.log;
  console.log = function () {
    log.call(this, 'My Console!!!', ...arguments);
  };
}());

可以簡單地:

 console.log = (m) => terminal.innerHTML = JSON.stringify(m)
 #terminal {background: black; color:chartreuse}
 $ > <span id="terminal"></span> <hr> <button onclick="console.log('Hello world!!')">3V3L</button> <button onclick="console.log(document)">3V3L</button> <button onclick="console.log(Math.PI)">3V3L</button>

由於我(還)無法對@ludovic-feltz 的答案發表評論,以下是他的答案已更正以允許在控制台中進行字符串插值:

// define a new console
var console = (function(oldCons){
    return {
        log: function(...text){
            oldCons.log(...text);
            // Your code
        },
        info: function (...text) {
            oldCons.info(...text);
            // Your code
        },
        warn: function (...text) {
            oldCons.warn(...text);
            // Your code
        },
        error: function (...text) {
            oldCons.error(...text);
            // Your code
        }
    };
}(window.console));

//Then redefine the old console
window.console = console;

為了完全攔截控制台,我們可以覆蓋每個方法:

const bindConsole=function(onMessage){
    Object.keys(console)
    .filter(type=>typeof(console[type])==='function')// *1
    .forEach(type=>{
        let _old=console[type];
        console[type] = function (...args) {
            _old.apply(console,args);
            onMessage(type,args);// *2
        };
    });
};

對於舊瀏覽器:

var bindOldConsole=function(onMessage){
    for(var k in console){// *1
        if(typeof(console[k])=='function')(function(type){
            var _old=console[type];
            console[type] = function () {
                _old.apply(console,arguments);
                onMessage(type,arguments);
            };
        })(k);
    }
};

  • *1 看起來控制台只有方法,但最好確定一下。

  • * 2您可以用替換這一行阻止從控制台的onMessage循環調用:

if(!isCyclic())onMessage(type,args);

// es6. Not sure concerning old browsers :(
const isCyclic=function (){
    let erst=(new Error()).stack.split('\n');
    return erst.includes(erst[1],2);
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM