Javascript 如何安全地包装`console.log`?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8785624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to safely wrap `console.log`?
提问by Dagg Nabbit
Suppose I want to include some calls to console.log
for some legitimate production reason, say for something like a unit test harness. Obviously I would not want this to throw a premature exception if the browser doesn't have a console
, or if no console is present.
假设我想包含一些console.log
出于合法生产原因的调用,比如单元测试工具。显然,如果浏览器没有console
,或者没有控制台,我不希望这会引发过早的异常。
What's the best way to create a simple log
function to log stuff to the console, or silently fail without error if no console is present?
创建一个简单的log
函数来将内容记录到控制台的最佳方法是什么,或者如果没有控制台,则无提示地失败而没有错误?
The accepted answer to the question linked above:
上面链接的问题的公认答案:
var log = Function.prototype.bind.call(console.log, console); log.apply(console, ["this", "is", "a", "test"]);
var log = Function.prototype.bind.call(console.log, console); log.apply(console, ["this", "is", "a", "test"]);
Can this log
function be called normally on IE, and the use of apply
here is just to show it's possible? And, I assume from the linked question that this will fail if IE's console is closed when it runs, so log
won't work even after the console opens, correct? If that's wrong, can someone explain how it works?
这个log
函数在IE上可以正常调用apply
吗,这里的使用只是为了说明可以吗?而且,我从链接的问题中假设,如果 IE 的控制台在运行时关闭,这将失败,因此log
即使在控制台打开后也无法工作,对吗?如果这是错误的,有人可以解释它是如何工作的吗?
This ycombinator articleseems relevant. Are they are talking about the same IE behavior as the question linked above?
这篇ycombinator 文章似乎很相关。他们是否在谈论与上面链接的问题相同的 IE 行为?
Function.prototype.apply.apply(console.log, [console, arguments]);
Works both on IE9 broken console.log, and regular console.log from other vendors. Same hack as using Array.prototype.slice to convert arguments into a real array.
Function.prototype.apply.apply(console.log, [console, arguments]);
适用于 IE9 损坏的 console.log 和来自其他供应商的常规 console.log。与使用 Array.prototype.slice 将参数转换为真实数组的技巧相同。
This works nicely in my chrome console.
这在我的 chrome 控制台中运行良好。
function echo(){
Function.prototype.apply.apply(console.log, [console, arguments]);
}
Simplified:
简化:
function echo(){
Function.apply.call(console.log, console, arguments);
}
Add a check and return:
添加检查并返回:
function echo(){
return window.console && console.log &&
Function.apply.call(console.log, console, arguments);
}
The example above looks adequate to me. I don't have IE on hand to test it, though. Is this a reasonable approach for safely wrapping console.log
?
上面的例子对我来说已经足够了。不过,我手头没有 IE 来测试它。这是安全包装的合理方法console.log
吗?
More questions
更多问题
Following the link in nav's answer below, we see the code:
按照下面导航的答案中的链接,我们可以看到代码:
Function.prototype.call.call(console.log, console,
Array.prototype.slice.call(arguments));
What is the purpose of converting arguments
to an array in this case? I guess it must fail in some browser if you don't do this? And, opera weird behavior and console-less browsers aside, shouldn't something like this pretty much work for every other browser as well? And does prototype
serve a purpose in the above examples, or are we just being pedantic... Function.call.call
or Object.call.call
or for that matter isNaN.call.call
seem to work just as well as Function.prototype.call.call
.
arguments
在这种情况下转换为数组的目的是什么?如果您不这样做,我想它一定会在某些浏览器中失败?而且,除了奇怪的行为和无控制台的浏览器之外,这样的事情不应该也适用于所有其他浏览器吗?并且确实prototype
在上述示例中起到了作用,或者我们只是迂腐……Function.call.call
或者Object.call.call
就此而言isNaN.call.call
似乎与Function.prototype.call.call
.
采纳答案by Andy E
Can this log function be called normally on IE, and the use of apply here is just to show it's possible?
这个日志函数在IE上能正常调用吗,这里用apply只是为了说明可以吗?
Yes, and yes. That particular example was aimed squarely at the "is it a real function"part of the linked question.
是的,是的。该特定示例直接针对链接问题的“它是一个真正的功能”部分。
And, I assume from the linked question that this will fail if IE's console is closed when it runs, so log won't work even after the console opens, correct?
而且,我从链接的问题中假设,如果 IE 的控制台在运行时关闭,这将失败,因此即使在控制台打开后日志也不会工作,对吗?
Correct. As explained in my answer on that question, the console
object is not exposed until the first time the developer tools are opened for a particular tab. Most developers use a console shim, in which case the Function#bind
approach becomes a little obsolete because you may as well use the Function#apply.apply
method.
正确的。正如我在该问题上的回答中所解释的那样,console
直到第一次为特定选项卡打开开发人员工具时,才会公开该对象。大多数开发人员使用控制台填充程序,在这种情况下,该Function#bind
方法有点过时了,因为您也可以使用该Function#apply.apply
方法。
What is the purpose of converting arguments to an array in this case?
在这种情况下将参数转换为数组的目的是什么?
There isn't one, it's redundant. Unless it's a custom logimplementation, in which case the developer may have a reason to convert an arguments object to an array.
没有,是多余的。除非它是自定义日志实现,在这种情况下,开发人员可能有理由将参数对象转换为数组。
And does prototype serve a purpose in the above examples, or are we just being pedantic...
原型在上面的例子中是否有用,或者我们只是在迂腐......
Well, yes and no. Some developer may have unwittingly changed Function.call
to a custom function or value. Of course, they could break Function.prototype.call
too, but this is far less likely to happen by accident.
嗯,是和不是。某些开发人员可能会在不知不觉中更改Function.call
为自定义函数或值。当然,它们也可能破裂Function.prototype.call
,但这种意外发生的可能性要小得多。
回答by dbrin
The problem with wrappers is that they will obfuscate file name and line number of the source of the log message.
包装器的问题在于它们会混淆日志消息源的文件名和行号。
Simple IE7 and below shim that preserves Line Numbering for other browsers:
为其他浏览器保留行编号的简单 IE7 及以下垫片:
/* console shim*/
(function () {
var f = function () {};
if (!window.console) {
window.console = {
log:f, info:f, warn:f, debug:f, error:f
};
}
}());
回答by ChrisN
Sorry, there was a bug in my post. Don't know how I missed it.
抱歉,我的帖子中有一个错误。不知道我是怎么错过的。
The PROPER way to create a global console object, if it does not exist:
创建全局控制台对象的正确方法(如果它不存在):
if (typeof console === "undefined"){
console={};
console.log = function(){
return;
}
}
回答by etoxin
I like to use:
我喜欢使用:
'console' in window && console.log("Boom!");
It works in all browsers and is easy to understand.
它适用于所有浏览器并且易于理解。
回答by Ammar Hasan
Try using the code snippet below... (this is my preferred approach because it makes you independent of window.console)
尝试使用下面的代码片段...(这是我的首选方法,因为它使您独立于 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))
So you may now try these in your code and see the result
所以你现在可以在你的代码中尝试这些并查看结果
logger.info("Hello");
logger.trace("Hello");
logger.debug("Hello");
logger.warn("Hello");
logger.error("Hello");
logger.log("Hello");
回答by dougajmcdonald
As a slight variation on Chris' answer, simply define 'log' as a property of 'console' with an empty function:
作为 Chris 答案的一个细微变化,只需将 'log' 定义为具有空函数的 'console' 属性:
if (typeof console === "undefined") {
console = {
log: function () {
return;
}
};
}
回答by Антон Баранов
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:
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);
回答by Nathan Long
Use Consolation
使用安慰
My ridiculously overengineered console:
我可笑的过度设计的控制台:
- prevents errors if there's no console
- prevents logging in production if you left
console.log
statements in your code - supports
console.error
,console.group
, and all such other methods - still gives you backtraces to your log statements
- 如果没有控制台,则防止错误
- 如果您
console.log
在代码中留下语句,则阻止登录生产 - 支持
console.error
,console.group
, 以及所有其他方法 - 仍然为您提供日志语句的回溯
It's amazing.
太奇妙了。
But really, you just shouldn't leave console
statements lying around in your code.
但实际上,您不应该console
在代码中留下语句。
Behold and tremble! Presenting: Consolation.js
看,颤抖吧!演示:Consolation.js
回答by Thomas W
Paul Irish has a nice light wrapper/replacement for console.log()
.
Paul Irish 有一个很好的轻型包装/替代品console.log()
。
http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
Advantages:
好处:
- Prevent errors if a console isn't around (i.e. IE)
- Maintains a history of logs, so you can look in the past if your console is added afterwards (e.g. firebug lite)
- Light & simple.
- Very quick to type --
log()
orwindow.log()
.
- 如果没有控制台(即 IE),则防止错误
- 维护日志的历史记录,因此您可以在之后添加控制台时查看过去(例如 firebug lite)
- 轻巧简单。
- 非常快速地输入 -
log()
或window.log()
.
回答by Kage
My solution is a little different. I create a standard shortcut for all console.log calls: In my case kag(whatever I want to report in the console).
我的解决方案有点不同。我为所有 console.log 调用创建了一个标准快捷方式:就我而言,kag(无论我想在控制台中报告什么)。
I test for IE, if IE I send the results to an alert box. If Chrome then displays in the console. This also means IE will always work even in console is closed:
我测试 IE,如果 IE,我将结果发送到警报框。如果 Chrome 显示在控制台中。这也意味着 IE 将始终工作,即使在控制台关闭时:
Code:
代码:
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. );
}
}
return rv;
}