如何安全地包装`console.log`?
假设我想包含一些调用console.log
的一些合法的生产原因,比如说unit testing工具。 显然,如果浏览器没有console
,或者没有控制台 ,我不希望这个引发过早的exception。
创build一个简单的log
function将日志logging到控制台的最好方法是什么,或者如果没有控制台存在,就会在没有错误的情况下悄然失败?
上面提到的问题被接受的答案是:
var log = Function.prototype.bind.call(console.log, console); log.apply(console, ["this", "is", "a", "test"]);
这个log
function可以在IE上正常调用,这里的apply
只是为了显示它是可能的? 而且,我从关联的问题中推测,如果IE的控制台在运行时closures,那么这样做会失败,所以即使在控制台打开后, log
也不能正常工作。 如果这是错的,有人可以解释它是如何工作的?
这ycombinator文章似乎相关。 他们是否正在谈论与上面链接的问题相同的IE行为?
Function.prototype.apply.apply(console.log, [console, arguments]);
在IE9破坏console.log和其他供应商的常规console.log上都可以。 与使用Array.prototype.slice将参数转换为实数组相同。
这在我的Chrome控制台中很好地工作。
function echo(){ Function.prototype.apply.apply(console.log, [console, arguments]); }
简化:
function echo(){ Function.apply.call(console.log, console, arguments); }
添加支票并返回:
function echo(){ return window.console && console.log && Function.apply.call(console.log, console, arguments); }
上面的例子对我来说足够了。 不过,我手边没有IE来testing它。 这是一个安全包装console.log
的合理方法吗?
更多的问题
在下面的导航答案中的链接,我们看到的代码:
Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
在这种情况下将arguments
转换为数组的目的是什么? 我想如果你不这样做,它肯定会在某些浏览器中失败? 而且,把歌剧怪异的行为和无控制台的浏览器放在一边,不应该像其他所有浏览器一样工作吗? prototype
服务于上述例子中的一个目的,或者我们只是迂腐… Function.call.call
或Object.call.call
或为此问题是isNaN.call.call
似乎工作就像Function.prototype.call.call
。
这个日志function可以在IE上正常调用,这里的应用只是为了显示它是可能的?
是的,是的。 这个特殊的例子是直接针对相关问题的“这是一个真正的function”的一部分。
而且,我从关联的问题中推测,如果IE的控制台在运行时closures,那么这样做会失败,所以即使在控制台打开后,日志也不能正常工作。
正确。 正如我在这个问题上的回答所解释的, console
对象在第一次为特定选项卡打开开发人员工具之前不会公开。 大多数开发人员使用控制台填充,在这种情况下, Function#bind
方法变得有些过时,因为您可以使用Function#apply.apply
方法。
在这种情况下将参数转换为数组的目的是什么?
没有一个,这是多余的。 除非是自定义日志实现,否则开发人员可能有理由将参数对象转换为数组。
在上面的例子中,原型服务于一个目的,还是我们只是迂腐…
那么,是的,不。 有些开发人员可能不知不觉地将Function.call
改为自定义函数或值。 当然,他们也可以打破Function.prototype.call
,但是这种事故不太可能发生。
包装器的问题是它们会混淆日志消息来源的文件名和行号。
简单的IE7和以下的垫片,保留其他浏览器的线路编号:
/* console shim*/ (function () { var f = function () {}; if (!window.console) { window.console = { log:f, info:f, warn:f, debug:f, error:f }; } }());
对不起,我的post中有一个错误。 不知道我错过了什么。
创build全局控制台对象的正确方法(如果不存在):
if (typeof console === "undefined"){ console={}; console.log = function(){ return; } }
我喜欢用:
'console' in window && console.log("Boom!");
它适用于所有浏览器,易于理解。
尝试使用下面的代码片段(这是我首选的方法,因为它使你独立于window.console)
var logger = (function (c) { "use strict"; var m = { log: function (a, t) { if (!c) { return; /* return or call your custom function here */ } var l = c.log, f = t === undefined ? l : (this.__dict__[t] || l); f.apply(c, a) }, __dict__: { "trace": c.trace, "debug": c.debug, "info": c.info, "warn": c.warn, "error": c.error } }; return { trace: function () { m.log(arguments, "trace"); }, debug: function () { m.log(arguments, "debug"); }, info: function () { m.log(arguments, "info"); }, warn: function () { m.log(arguments, "warn"); }, error: function () { m.log(arguments, "error"); }, log: function () { m.log(arguments, undefined); } }; }(window.console))
所以你现在可以在你的代码中尝试这些,看看结果
logger.info("Hello"); logger.trace("Hello"); logger.debug("Hello"); logger.warn("Hello"); logger.error("Hello"); logger.log("Hello");
作为克里斯答案的一个小小的变化,只需用一个空的函数将'log'定义为'console'的一个属性:
if (typeof console === "undefined") { console = { log: function () { return; } }; }
保罗爱尔兰有一个很好的轻包装/替代console.log()
。
http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
优点:
- 防止错误,如果控制台不在身边(即IE)
- 保持日志的历史,所以你可以看过去,如果你的控制台后来添加(如萤火虫)
- 轻而简单。
- input很快
log()
或window.log()
。
使用安慰
我可笑的过度工程控制台:
- 防止错误,如果没有控制台
- 如果您在代码中保留
console.log
语句,将阻止生产日志 - 支持
console.error
,console.group
和所有其他方法 - 仍然给你回溯到你的日志语句
太奇妙了。
但是,真的,你不应该把console
声明留在你的代码中。
看,战栗! 介绍: Consolation.js
CoffeeScript的:
empty_function = -> return if !window.console? window.console = {} for fn in ['log', 'info', 'warn', 'debug', 'error'] if (typeof window.console[fn] isnt 'function') window.console[fn] = empty_function
JS:
(function() { var empty_function, fn, i, len, ref; empty_function = function() {}; if (window.console == null) { window.console = {}; ref = ['log', 'info', 'warn', 'debug', 'error']; for (i = 0, len = ref.length; i < len; i++) { fn = ref[i]; if (typeof window.console[fn] !== 'function') { window.console[fn] = empty_function; } } } }).call(this);
我的解决scheme有点不同。 我为所有的console.log调用创build一个标准的快捷方式:在我的情况下kag(无论我想在控制台中报告)。
我testing的IE浏览器,如果IE我把结果发送到一个警告框。 如果Chrome然后显示在控制台。 这也意味着即使在控制台closures的情况下,IE也会一直工作:
码:
var iever = getInternetExplorerVersion(); if(iever>-1){ function kag(params){ alert(params); } } else { var kag = console.log.bind(console, "REPORT: "); } function getInternetExplorerVersion() { var rv = -1; if (navigator.appName == 'Microsoft Internet Explorer') { var ua = navigator.userAgent; var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); if (re.exec(ua) != null){ rv = parseFloat( RegExp.$1 ); } } return rv; }
- 什么错误缩放:1; 修复CSS?
- 在任何低于10的IE版本中,XMLHttpRequest访问被AngularJS拒绝
- Internet Explorer 11检测
- 为什么Internet Explorer不能在失败后的Ajax调用中发送HTTP POST主体?
- 如何修复JavaScript的Internet Explorer浏览器中的Array indexOf()
- “X-UA-Compatible”content =“IE = 9; IE = 8; IE = 7; IE = EDGE”
- Internet Explorer忽略某些域上的Cookie(无法读取或设置Cookie)
- 使用标签强制IE兼容模式closures
- button点击事件在不同的input按下回车键(没有窗体)