【问题标题】:"Un-redefining" Google Chrome's console Object“取消重新定义”谷歌浏览器的控制台对象
【发布时间】:2011-09-02 03:57:08
【问题描述】:

我正在处理一个系统,其中在页面的早期执行以下 Javascript 代码(这是我无法控制的)

if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}

此代码似乎用于创建模拟 console 对象,以防止在没有 javascript 控制台的环境中出现 javascript 错误。这很好,除了它还会阻止 Google Chrome 的控制台运行。条件显式检查firebug,仅此而已

    if (!("console" in window) || !("firebug" in console))

那么,有没有办法告诉 Chrome 的调试器重新初始化它的控制台对象?也就是说,用简单的英语告诉 Chrome

嘿,你知道什么时候加载一个页面并定义一个控制台对象供我使用吗?再做一次,这样我们就可以覆盖用户空间中某人所做的事情。

我意识到我可以做类似的事情

console.firebug = "faketrue";

并捕获了条件,但我在系统中受到限制,并且无法在上述控制台重新定义命中之前添加 javascript。换句话说,不,我不能只是在头部开始之后添加一点javascript代码。

【问题讨论】:

  • @Rocket:重新阅读问题。该代码超出了我的控制范围。我正在尝试撤消它的影响。
  • @Alan:我错过了。这段代码是谁写的?去告诉他们这是错的!
  • 您能创建一个不可见的 iframe 并从该窗口复制 window.console 吗?
  • @Rocket:并非所有问题都是技术问题
  • chrome 是您唯一需要担心的浏览器吗?还是所有非火狐浏览器?

标签: javascript google-chrome google-chrome-devtools


【解决方案1】:

你不能把自己的脚本直接放在html的头部就在最上面吗?

<script ...>
    if (console) { window.cache_console = console; }
</script>
</head>
<body>
... html ...

<script>
    window.console = window.cache_console;
</script>
</body>
</html>

你不能比在 HEAD 中更早得到。

【讨论】:

  • 你知道我怎么说“但是我在系统中受到限制,没有办法在上面的控制台重新定义命中之前添加javascript。”。当我这么说时,我的意思是“但我在系统中受到限制,并且无法在上述控制台重新定义命中之前添加 javascript。”
  • @Alan:你用的是什么系统?必须有办法修复原始代码。
【解决方案2】:

我相信您可以通过 iframe 注入来执行此操作,然后复制 iframe 的控制台对象:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
</script>
<iframe id="text"></iframe>
<script type="text/javascript">
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
</script>

http://jsfiddle.net/nmY6k/

注意,这只是一个概念应该有效的演示。

编辑

使用纯 JS iframe:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
</script>

http://jsfiddle.net/nmY6k/1/

编辑

当然,如果您之后需要移除 iframe 元素:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
console.log(typeof window.frames);
document.body.removeChild(iframe);
console.log(typeof window.frames);
</script>

【讨论】:

  • 没问题,很高兴我能帮上忙。
  • 您的第一个示例在 Chrome 14.0 上抛出“无控制台”
  • 如果窗口上已有其他 iframe,您将需要使用 console = window.frames[window.frames.length-1].console。或如@jontro console = iframe.contentWindow.console 的回答所建议的那样
【解决方案3】:

这似乎有效:

iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = iframe.contentWindow.console;

但是看起来您无法删除 iframe

【讨论】:

    【解决方案4】:

    假设您担心的原因是您希望在开发时正常使用控制台,您可以创建一个简单的 chrome 扩展来定义 console.firebug,以便条件评估为 false。这样您就不必担心使用其他框架的控制台对象可能会出现任何潜在的古怪行为,也不必担心在开发/部署时重复插入和删除 hack。

    【讨论】:

    • 有趣,但假设您了解 Chrome 扩展 API。
    【解决方案5】:

    在 Google Chrome 中,删除 console 对象有效:

    <script>
    window.console = {};
    delete console;
    console.log('still works');
    </script>
    

    但是,这在 Firefox 4 中似乎不起作用。不过,这只是一个开始。

    【讨论】:

    • 不错,值得一票,但 @Jarde 以聪明和广泛的适用性获胜。
    • 这仅仅是因为控制台命令行的怪癖在 eval 上下文中执行,例如 @KangaX 的 perfectionkills.com/understanding-delete 吗?
    • 2019 年,这个答案似乎不起作用。在 Chrome 中 delete console 不会重新创建控制台,它只是将其删除。
    【解决方案6】:

    您可以按照上面的建议编写一个非常基本的用户脚本来分配控制台。然后进入该用户脚本的 manifest.json,并将 run_at 设置(参见http://code.google.com/chrome/extensions/content_scripts.html)更改为 document_start。这将使用户脚本现在运行 before 任何页面脚本运行,因此在控制台被弄乱之前。

    ...编辑...

    实际上,我从http://blog.chromium.org/2011/07/chrome-extensions-now-with-more.html 注意到,chrome 现在也支持@run-at,因此您可以设置它,甚至不必直接与 manifest.json 混淆。他们在http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/userscript-runat/runat.user.js?view=markuphttp://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/userscript-runat/runat.user.js?view=markup有一个使用@run-at at document_start 的示例脚本

    【讨论】:

      【解决方案7】:

      这是我根据之前的答案写的一个方法。它有一些额外的逻辑,因此您可以多次调用它而无需重新创建 iframe。

      function fixConsole() {
      
          var iframe;
          if(!(iframe = document.getElementById('fixConsole'))) {
              iframe = document.createElement('iframe');
              iframe.id = 'fixConsole';
              document.body.appendChild(iframe);
          }
          delete console;    
          console = iframe.contentWindow.console;
      
      };
      

      如果最初重新定义 console 的代码正在自我修复,我预计需要多次调用 fixConsole

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        • 2018-10-16
        • 2014-09-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多