Google Chrome console.log()与对象和数组不一致

Google Chrome console.log() inconsistency with objects and arrays

本文关键字:对象 数组 不一致 Chrome console log Google      更新时间:2023-09-26

我今天正在帮助同事调试一些代码,我注意到console.log()在Google Chrome中的奇怪行为:

如果你:

  1. 创建一个嵌套的数组(例如,[[345年,"测试"]])

  2. console.log()将数组记录到控制台

  3. 修改数组内部的一个值,然后console.log()将输出后面的值——而不是 console.log()执行时数组的值。

JavaScript

:

var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]
var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}

var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]
<<p> JSFiddle例子/strong>

此行为在Firefox中不会发生。

还需要注意的是,如果我在Chrome调试器中逐行执行他的代码,那么console.log()将输出正确的值。

这个奇怪的现象是否有一个解释,或者它只是一个bug与谷歌浏览器?

编辑:

我已经缩小了复制不一致的console.log()行为的步骤:

如果您将此脚本添加到您的页面:

var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
    greetings.push('goodbye');
},3000);

并在Chrome 控制台窗口已经打开的新窗口中打开它,那么console.log()输出将不同于如果您加载页面与控制台窗口关闭。这里有一个JSFiddle来演示这个

在第一种情况下,控制台窗口已经打开,console.log()将输出数组的当前值(即两个项)。

在第二种情况下,控制台窗口最初关闭,在页面加载后只打开console.log()将输出数组的后面值(即三个项)。

这是一个bug在谷歌Chrome的console.log()功能?

经过大量的挖掘,我发现这已经被报告为一个错误,在Webkit中修复,但显然还没有被拉入谷歌Chrome。

据我所知,这个问题最初是在这里报告的:https://bugs.webkit.org/show_bug.cgi?id=35801:

来自mitch kramer 2010-03-05 11:37:45 PST

1)创建一个具有一个或多个属性的对象字面值

2) console.log该对象,但保持关闭状态(不要在控制台中展开它)

3)将其中一个属性更改为新值

现在打开console.log,你会看到它由于某种原因有了新的值,即使它的值在生成时是不同的。

我应该指出,如果你打开它,它将保留正确的值,如果不清楚。

来自Chromium开发人员的响应:

评论#2来自Pavel Feldman 2010-03-09 06:33:36 PST

我认为我们永远不会解决这个问题。我们不能克隆对象转储到控制台,我们也不能监听对象属性的变化,以使它始终是实际的。

我们应该确保现有的行为是预期的。

修复在两年半后的2012年8月9日,Webkit (http://trac.webkit.org/changeset/125174)实现了,但它似乎还没有进入Chrome。

从今天开始,将对象(数组)转储到控制台将导致对象的属性为读取控制台对象扩展(即惰性)。这意味着在修改它将很难使用控制台进行调试。

此更改开始在对象/数组的初始化时生成简短的预览记录并将此信息传递到前端。这只发生在前端已打开,它只适用于console.log(),而不适用于实时控制台交互。

我找到了一个解决这个bug/特性的方法。

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

编辑:不幸的是,这将不工作的非基本值,如函数。在这里使用另一个克隆工具。

jQuery的例子:

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