为什么在IE中只有在打开开发者工具后才能运行JavaScript?

667

IE9 Bug-只有在打开开发者工具后JavaScript才能正常工作。

我们的网站向用户提供免费的PDF下载,并具有一个简单的“输入密码以下载”的功能。 但是,在Internet Explorer中根本无法正常工作。

您可以在此示例中亲自查看。

下载口令为“makeuseof”。在任何其他浏览器中,它都可以正常运行。 在IE中,两个按钮都没反应。

我发现最奇怪的事情是,如果你用F12打开和关闭开发人员工具,它就突然开始工作了。

我们尝试过兼容性模式等,但没有任何效果。

如何使其在Internet Explorer中正常工作?


4
使用跨浏览器包装器:https://github.com/MichaelZelensky/log.js - Michael Zelensky
3
如果你有一个构建步骤,一个好的选择是使用类似于 gulp-strip-debug 的工具。它可以移除所有的 console.* 方法,非常适合生产环境的构建或在 IE 中进行测试。 - knownasilya
17
未来的谷歌搜索用户:我有与IE11中相同的症状。事实证明答案与“console”无关,而是与我的使用angular和缓存get请求有关。请查看此处的答案[https://dev59.com/YGQo5IYBdhLWcg3wXuin]和此处的答案[https://dev59.com/dWQn5IYBdhLWcg3wRVRs]获取更多信息。 - Christoffer Lette
1
@ChristofferLette 是的,我有同样的问题,请查看http://stackoverflow.com/questions/31428126/not-getting-object-file-from-a-file-input-html-control-using-jquery-and-javasc.....当开发者工具打开时,代码可以正常工作。 - Pranav Bilurkar
8
这类问题最令人烦恼的是什么?它们几乎不可能调试,因为一旦打开开发者控制台,它就开始正常工作了。 - jlewkovich
12个回答

834

听起来你的 JavaScript 代码中可能有一些调试代码。

你所描述的体验是常见的代码中包含 console.log() 或任何其他 console 功能。

console 对象只有在打开Dev工具栏后才会激活。在此之前,调用 console 对象将导致其被报告为 undefined。工具栏打开后,控制台就存在了(即使随后关闭了工具栏),因此您的控制台调用将正常工作。

有几种解决方法:

最明显的方法是通过删除对 console 的引用来检查你的代码。无论如何,你都不应该在生产代码中留下这样的东西。

如果想保留控制台引用,可以将它们包装在一个 if() 语句或其他条件中,以在尝试调用之前检查控制台对象是否存在。


9
留下调试代码的解决方法有哪些?IE 是唯一一个会出现这种愚蠢行为的浏览器... - Meekohi
95
如果没有控制台对象,就创建一个名为console的空对象,并赋予其一个不输出任何内容的log方法。 - Meekohi
82
if(!console)会导致相同的错误,应该改为if(!window.console) - mindplay.dk
11
因此,IE不应该实现每个新的js开发人员经常使用的功能,以避免让一些使用脚本修复本应在第一时间就能正常工作的事情的开发人员感到烦恼......但是因此责怪IE是不公平的吗?你是一个非常慷慨的人,Spudley! :) - Jordan Davis
8
仍然会在IE11上发生。 - Michael
显示剩余9条评论

167

HTML5 Boilerplate提供了一段方便的代码,可用于修复控制台问题:

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

正如评论中所指出的,最新版本可在 GitHub 页面 上获取。


10
@plus评论中的链接已经失效。代码已被推送到“src”子目录中:https://github.com/h5bp/html5-boilerplate/blob/master/src/js/plugins.js - Christoffer Lette
1
它已经从HTML5 Boilerplate存储库中删除。最后一个版本是这个 - CrazyPenguin

158

除了 console.log 问题之外(至少在 IE11 中),还存在另一个可能的原因:

当控制台未打开时,IE会进行相当激进的缓存,因此请确保任何 $.ajax 调用或 XMLHttpRequest 调用的缓存设置为false。

例如:

$.ajax({cache: false, ...})

当开发者控制台打开时,缓存会变得不那么积极。似乎是一个错误(或者也许是一种特性?)


10
这真的帮了我一大忙 ;) 谢谢!我认为这是一个bug,因为你应该在打开和关闭控制台时具有相同的条件来测试和调试你的网站。 - Chnoch
1
对我有用。具体来说:https://dev59.com/vmYr5IYBdhLWcg3wytHe - user1062589
3
这个应该更高,因为我认为这才是实际的答案...在某些IE版本中,关于console.log的接受答案会抛出错误,而不是引起这里描述的行为。 - Migs

66

在我做了一个小改动之后,这解决了我的问题。我在我的HTML页面中添加了以下内容,以解决IE9的问题:

<script type="text/javascript">
    // IE9 fix
    if(!window.console) {
        var console = {
            log : function(){},
            warn : function(){},
            error : function(){},
            time : function(){},
            timeEnd : function(){}
        }
    }
</script>

2
此解决方案在Windows 7 64位上的IE 11上无法正常工作。 - Vikram
2
这解决了我的问题,在 Windows 7 64 位上的 IE 11。 - zonyang

31
除了接受的答案和其他人提到的“console”使用问题之外,有至少另一个原因解释为什么在Internet Explorer中有时只有启用开发人员工具才能正常工作的页面。
当启用开发人员工具时,IE并没有像正常模式下那样真正使用它的HTTP缓存(至少在IE 11中默认情况下是这样)。
这意味着如果您的网站或页面存在缓存问题(例如,如果它缓存超出应有的范围-这就是我的情况),则在F12模式下您将无法看到该问题。因此,如果JavaScript执行一些已缓存的AJAX请求,则可能无法在正常模式下按预期工作,并且在F12模式下可以正常工作。

2
请参考https://dev59.com/-G865IYBdhLWcg3wHKpe了解如何禁用缓存xmlHttpReq请求。 - Michael Ross
3
甜的。这很出乎意料地奏效了。我想Angular的$http服务并没有像我想象中那样进行缓存破坏。 - user499054

18

我猜这可能有所帮助,在任何javascript标签之前添加此内容:

try{
  console
}catch(e){
   console={}; console.log = function(){};
}

12
使用try catch来检测变量是否存在是不好的做法。这不仅会降低运行速度,而且如果您在try块中有多个语句,则可能因为其他原因而导致异常。请不要使用此方法,至少使用if (typeof console == 'undefined') - Ruan Mendes

9
如果您正在使用AngularJS 1.X版本,可以使用$log服务来代替直接使用console.log。
“用于记录日志的简单服务。默认实现将消息安全地写入浏览器的控制台(如果存在)。 ”

https://docs.angularjs.org/api/ng/service/$log

所以,如果您有类似的东西

angular.module('logExample', [])
  .controller('LogController', ['$scope', function($scope) {
    console.log('Hello World!');
 }]);

你可以用它替换

angular.module('logExample', [])
  .controller('LogController', ['$scope', '$log', function($scope, $log) {
    $log.log('Hello World!');
 }]);

Angular 2+ 没有内置的日志服务


1
这对我很有帮助,谢谢 - 对于其他使用TypeScript的人来说,这是Angular定义中的“ILogService”。 - DannykPowell
据我所知,使用 $log 会导致日志语句的位置被隐藏,而使用 console.log 则不会。在开发过程中,这并不是很好的体验。 - JesseDahl

7

如果您正在使用 angular,并且使用的是ie浏览器版本 9,10 edge 浏览器,请使用以下代码:

myModule.config(['$httpProvider', function($httpProvider) {
    //initialize get if not there
    if (!$httpProvider.defaults.headers.get) {
        $httpProvider.defaults.headers.get = {};    
    }    

    // Answer edited to include suggestions from comments
    // because previous version of code introduced browser-related errors

    //disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
    // extra
    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
}]);

完全禁用缓存


5

对于我来说,这发生在IE 11上。我正在调用jquery的.load函数。 所以我用了一种老式的方法,在URL中加入一些内容来禁用缓存。

$("#divToReplaceHtml").load('@Url.Action("Action", "Controller")/' + @Model.ID + "?nocache=" + new Date().getTime());

4

我有另一种方案,可以替代 runekstodotresde 提供的解决方案,还可以避免在评论中讨论 Spudley 的答案时出现的问题:

        try {
            console.log(message);
        } catch (e) {
        }

这段代码看起来略显混乱,但另一方面它简洁明了,涵盖了runeks的答案中提到的所有日志记录方法,而且它有一个巨大的优势,就是你可以随时打开IE的控制台窗口,查看日志。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接