如何使console.log显示对象的当前状态?


146

在没有附加组件的Safari(实际上是大多数其他浏览器)中,console.log将在最后执行状态而不是在console.log调用时的状态下显示对象。

我必须克隆对象只是为了通过它输出console.log以获取该行的对象状态。

例:

var test = {a: true}
console.log(test); // {a: false}
test.a = false; 
console.log(test); // {a: false}

2
问题的jsfiddle示例和下面给出的各种解决方案:jsfiddle.net/luken/M6295
路加福音

7
日志功能将实时引用输出到对象是非常违反直觉的。这就是所谓的手表,它与日志条目有很大不同。记录对象时执行此操作比记录存储原始值的变量时更有意义。
faintsignal

2
我怎么从来没有遇到过?我觉得这令人恐惧
ErikAGriffin

Answers:


171

我认为您正在寻找console.dir()

console.log()不会执行您想要的操作,因为它会打印对对象的引用,并且在您将其弹出时将其更改。console.dir调用时在对象中打印属性的目录。

下面的JSON想法是一个好主意;您甚至可以继续解析JSON字符串,并获得类似.dir()的可浏览对象:

console.log(JSON.parse(JSON.stringify(obj)));


38
对我来说,Chrome13 console.log和之间没有区别console.dir
Andrew D.

嗯,这令人惊讶-它可以在Firebug中使用。我以为Webkit中也是如此。
evan

1
我在Chrome中看到的是,如果您在运行log语句后打开控制台,则在扩展它时会进行延迟评估。但是,如果控制台已经打开(例如,打开控制台,然后在页面上单击“刷新”),它将进行急切的评估-即在运行log语句时打印值。
Polemarch

6
另外,dir是JSON的副本,而shallow-copy是deep-copy的副本。console.dir()将仅评估顶级对象的属性(不会评估其他更深层嵌套的对象),而JSON将递归进行。
Polemarch

9
同样,对我来说console.dir,在Chrome浏览器(v33)中也不起作用。这是人们提供的解决方案的比较:jsfiddle.net/luken/M6295
路加福音

71

如果要在记录日志时查看其状态,通常要做的就是将其转换为JSON字符串。

console.log(JSON.stringify(a));

4
太好了,对我来说是个很好的提示:我只需要再次解析它就可以在控制台中放置我的对象。 function odump(o){ console.log($.parseJSON(JSON.stringify(o))); }
克里斯(Chris

1
谢谢这对我有用!console.dir没有打印出来
ah-shiang han

1
如果您的对象碰巧包含圆形结构怎么办?
Alex McMillan 2014年

1
@AlexMcMillan您可以使用多个之一 ,该 库允许使用循环引用对对象进行JSON字符串化。
Alex Turpin 2014年

7
真是的 这应该是一件简单,显而易见的事情。相反,我们必须进行字符串化,解析,记录并使用特殊的循环引用库!我认为浏览器需要更好地支持简单的调试需求。
火星

26

香草JS:

@evan的答案似乎在这里最好。只需(ab)使用JSON.parse / stringify有效地复制对象。

console.log(JSON.parse(JSON.stringify(test)));

jQuery的特定解决方案:

您可以使用以下命令在某个时间点创建对象的快照: jQuery.extend

console.log($.extend({}, test));

此处实际发生的情况是jQuery正在使用test对象的内容创建一个新对象,并对其进行记录(因此它不会更改)。

AngularJS(1)具体解决方案:

Angular提供了copy可以用来达到相同效果的函数:angular.copy

console.log(angular.copy(test));

香草JS包装器功能:

这是一个包装console.log但将在注销之前复制所有对象的函数。

我写这篇文章是为了回答答案中一些类似但功能不强的功能。它支持多个参数,并且如果它们不是常规对象,则不会尝试复制它们。

function consoleLogWithObjectCopy () {
  var args = [].slice.call(arguments);
  var argsWithObjectCopies = args.map(copyIfRegularObject)
  return console.log.apply(console, argsWithObjectCopies)
}

function copyIfRegularObject (o) {
  const isRegularObject = typeof o === 'object' && !(o instanceof RegExp)
  return isRegularObject ? copyObject(o) : o
}

function copyObject (o) {
  return JSON.parse(JSON.stringify(o))
}

用法示例consoleLogWithObjectCopy('obj', {foo: 'bar'}, 1, /abc/, {a: 1})


6

> Object在控制台中,不仅显示当前状态。实际上,它会延迟读取对象及其属性,直到您对其进行扩展。

例如,

var test = {a: true}
console.log(test);
setTimeout(function () {
    test.a = false; 
    console.log(test);
}, 4000);

然后展开第一个电话,如果在第二个电话console.log返回之前进行,那将是正确的


2

使用Xeon06的提示,您可以在一个对象中解析他的JSON,这是我现在用来转储对象的日志函数:

function odump(o){
   console.log($.parseJSON(JSON.stringify(o)));
}

1

我定义了一个实用程序:

function MyLog(text) {
    console.log(JSON.stringify(text));
}

当我想登录控制台时,我只需执行以下操作:

MyLog("hello console!");

效果很好!



1

有一个使用调试器库的选项。

https://debugjs.net/

只需将脚本包含在您的网页中并放入日志语句即可。

<script src="debug.js"></script>

记录中

var test = {a: true}
log(test); // {a: true}
test.a = false; 
log(test); // {a: false}

0

我可能会建议这样做,但可以采取进一步的措施。我们可以直接扩展控制台对象本身以使其更加清晰。

console.logObject = function(o) {
  (JSON.stringify(o));
}

我不知道这是否会引起时空连续体中某种类型的库碰撞/核熔毁/破裂。但这在我的qUnit测试中效果很好。:)


1
这不会记录任何内容。它只是吞并了对某些内容进行字符串化的结果。有趣的是,它获得了投票
Zach Lysobey

0

在打开控制台后刷新页面,或在将请求提交到目标页面之前打开控制台...。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.