【问题标题】:Restoring console.log()恢复 console.log()
【发布时间】:2011-10-28 16:49:27
【问题描述】:

由于某种原因,Magento 附带的原型框架(或其他 JavaScript 代码)正在替换标准控制台功能,因此我无法调试任何东西。在 JavaScript 控制台 console 中写下来,我得到以下输出:

> console
Object
assert: function () {}
count: function () {}
debug: function () {}
dir: function () {}
dirxml: function () {}
error: function () {}
group: function () {}
groupEnd: function () {}
info: function () {}
log: function () {}
profile: function () {}
profileEnd: function () {}
time: function () {}
timeEnd: function () {}
trace: function () {}
warn: function () {}

我在 Linux 上使用Google Chrome version 13.0.782.112

Prototype JavaScript framework, version 1.6.0.3

有没有快速解决这个问题的方法?

【问题讨论】:

标签: javascript google-chrome prototypejs console.log


【解决方案1】:

以防万一有人面临同样的情况。 我没有回复 Xaerxess 的原始答案,因为我没有足够的声誉来做这件事。 看起来这是正确的答案,但由于某种原因,我注意到它有时可以在我的软件中运行,有时不能...

所以我尝试在运行脚本之前完成删除,看起来一切正常 100% 次。

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

  console.log = null;
  console.log;         // null

  delete console.log;

  // Original by Xaerxess
  var i = document.createElement('iframe');
  i.style.display = 'none';
  document.body.appendChild(i);
  window.console = i.contentWindow.console;

}

谢谢大家。

【讨论】:

  • 这不应该是现在接受的答案吗,因为原来接受的答案在最新的 Chrome 或 Firefox 上不再适用?
  • 这对我有用。只是做delete console.log 没有用,所以这应该是公认的答案。
【解决方案2】:
function restoreConsole() {
  // Create an iframe for start a new console session
  var iframe = document.createElement('iframe');
  // Hide iframe
  iframe.style.display = 'none';
  // Inject iframe on body document
  document.body.appendChild(iframe);
  // Reassign the global variable console with the new console session of the iframe 
  console = iframe.contentWindow.console;
  window.console = console;
  // Don't remove the iframe or console session will be closed
}

在 Chrome 71 和 Firefox 65 上测试

【讨论】:

  • 这与@Xaerxess 的答案相同,如果您查看他的答案的 cmets,您会收到针对新 Chrome 版本的警告...您也可以支持他的回答并支持评论,无需重复。
  • @balexandre 是不一样的,因为这个函数不会删除孩子,那么如果你不删除孩子仍在工作,否则控制台不会打印任何内容:)
  • 仅仅因为你改变了一行代码,不应该是一个新的答案...... Stackoverflow不是衡量如何编写更好的代码,而是帮助下一个快速得到正确答案。
【解决方案3】:

由于原始控制台位于 window.console 对象中,请尝试从 iframe 恢复 window.console

var i = document.createElement('iframe');
i.style.display = 'none';
document.body.appendChild(i);
window.console = i.contentWindow.console;
// with Chrome 60+ don't remove the child node
// i.parentNode.removeChild(i);

在 Chrome 14 上为我工作。

【讨论】:

  • 对于任何打算使用它的人,记得自己清理。又名:i.parentNode.removeChild(i);
  • 这个答案实际上适用于当前版本的 Chrome (52+),而接受的答案则不行。
  • 这是我见过的最有创意的答案!谢谢。
  • @NickCoad 在上次i.parentNode.removeChild(i) 之后仍然有效,不是吗?
  • 我使用的是 Chrome 63 (Canary),这个答案有效,但只有没有 i.parentNode.removeChild(i); 行。
【解决方案4】:

此问题中给出的解决方案在新浏览器中不再正确解决此问题。正如@Xaerxess 所说,唯一(某种)工作的是从<iframe> 抓住控制台。

我写了一个用户脚本来保护控制台不被覆盖。它不会破坏任何覆盖控制台的工具——它同时调用被覆盖的方法和原始方法。当然也可以包含在网页中。

// ==UserScript==
// @name        Protect console
// @namespace   util
// @description Protect console methods from being overriden
// @include     *
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==
{

    /**
      * This object contains new methods assigned to console.
      * @type {{[x:string]:Function}} **/
    const consoleOverridenValues = {};
    /**
      * This object contains original methods copied from the console object
      * @type {{[x:string]:Function}} **/
    const originalConsole = {};
    window.originalConsole = originalConsole;
    // This is the original console object taken from window object
    const originalConsoleObject = console;
    /**
     * 
     * @param {string} name
     */
    function protectConsoleEntry(name) {
        const protectorSetter = function (newValue) {
            originalConsole.warn("Someone tried to change console." + name + " to ", newValue);
            consoleOverridenValues[name] = function () {
                /// call original console first
                originalConsole[name].apply(originalConsoleObject, arguments);
                if (typeof newValue == "function") {
                    /// call inherited console
                    newValue.apply(window.console, arguments);
                }
            }
        }
        const getter = function () {
            if (consoleOverridenValues[name])
                return consoleOverridenValues[name];
            else
                return originalConsole[name];
        }
        Object.defineProperty(console, name, {
            enumerable: true,
            configurable: false,
            get: getter,
            set: protectorSetter
        });
    }

    /*
     *** This section contains window.console protection
     *** It mirrors any properties of newly assigned values
     *** to the overridenConsoleValues
     *** so that they can be used properly
    */

    /** 
      * This is any new object assigned to window.console
      * @type {Object} **/
    var consoleOverridenObject = null;
    /// Separate boolean is used instead
    /// of checking consoleOverridenObject == null
    /// This allows null and undefined to be assigned with 
    /// expected result
    var consoleIsOverriden = false;

    for (var i in console) {
        originalConsole[i] = console[i];
        protectConsoleEntry(i);
    }

    Object.defineProperty(window, "console", {
        /// always returns the original console object
       /// get: function () { return consoleIsOverriden ? consoleOverridenObject : originalConsoleObject; },
        get: function () { return originalConsoleObject; },
        set: function (val) {
            originalConsole.log("Somebody tried to override window.console. I blocked this attempt."
                + " However the emulation is not perfect in this case because: \n"
                + "     window.console = myObject;\n"
                + "     window.console == myObject\n"
                + "returns false."
            )
            consoleIsOverriden = true;
            consoleOverridenObject = val;

            for (let propertyName in val) {
                consoleOverridenValues[propertyName] = val[propertyName];
            }
            return console;
        },
    });
}

【讨论】:

    【解决方案5】:

    delete window.console 在 Firefox 和 Chrome 中恢复原始的 console 对象。

    这是如何工作的? window 是一个托管对象,通常它通过所有实例之间的通用原型实现(您在浏览器中有许多选项卡)。

    外部库/框架(或Firebug 等)的一些愚蠢的开发人员会覆盖window 实例的属性控制台,但它不会破坏window.prototype。通过delete 操作符,我们从console.* 方法返回到原型代码的调度。

    【讨论】:

      【解决方案6】:

      例如,

      delete console.log
      

      也会恢复console.log:

      console.log = null;
      console.log;         // null
      
      delete console.log;
      console.log;         // function log() { [native code] }
      

      【讨论】:

      • 是的!这更好!这就是我喜欢stackoverflow的原因:D
      • 试试delete window.console,这在chrome 30.x中对我有用;
      • 不再在 Chrome 52 中工作。可以在 Twitter 上测试,例如:console.log -> function() {},删除 console.log 或 window.console.log 只会将其删除,不会恢复原始行为。
      • 可以确认...它在较新的 chrome 中不起作用。我正在扩展owncloud,他们删除了console.log(WTF?)
      • 这是一个技巧,可能有助于 Chrome 在使用 delete console.log 时不恢复本机日志功能...如果您愿意安装(或已经拥有)TamperMonkey,那么您只需要一个简单的脚本... setTimeout(() => { unsafeWindow.console = window.console; }, 2000); Tampermonkey 脚本获取自己的 window 对象副本,因此您需要做的就是在延迟后恢复原始控制台对象。根据需要进行调整...(确保删除默认的 // @grant none)。
      【解决方案7】:

      Magento 在/js/varien/js.js 中有以下代码 - 将其注释掉即可。

      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() {}
      }
      

      【讨论】:

        【解决方案8】:

        在脚本开头的变量中保存对原始console 的引用,然后使用此引用,或重新定义console 以指向捕获的值。

        例子:

        var c = window.console;
        
        window.console = {
            log :function(str) {
                alert(str);
            }
        }
        
        // alerts hello
        console.log("hello");
        
        // logs to the console
        c.log("hello");
        

        【讨论】:

        • 当然我可以做到,在一切之前注入一些 JS,我确信这个解决方案有效,但我想要一种快速解决问题的方法。还是谢谢
        猜你喜欢
        • 2013-12-25
        • 2015-12-24
        • 2016-11-02
        • 1970-01-01
        • 2012-07-09
        • 2012-11-29
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        相关资源
        最近更新 更多