为什么在第一个和第二个console.log()中我得到了相同的结果

9 浏览
0 Comments

为什么在第一个和第二个console.log()中我得到了相同的结果

我将从代码开始:

var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);

简单吧?对此,Firefox控制台显示:

[ "hi" ]
[ "bye" ]

很棒,但是Chrome的JavaScript控制台(7.0.517.41 beta版本)显示:

[ "bye" ]
[ "bye" ]

我做错了什么吗,还是Chrome的JavaScript控制台在评估我的数组时特别懒散?

0
0 Comments

在上面的代码中,问题出现在console.log函数中。当我们尝试使用console.log打印出一个数组时,如果我们直接传递数组作为参数,那么在控制台输出的结果将会是一个引用,而不是数组的副本。这意味着当我们修改原始数组时,控制台输出的结果也会随之改变。

为了解决这个问题,我们可以使用Array#slice方法来克隆一个数组。在console.log中使用slice方法可以得到正确的结果。

除了使用slice方法克隆数组之外,我们还可以使用一个自定义的函数console.logShallowCopy来代替console.log。这个函数可以避免上述问题的发生。它会将传入的参数进行克隆,然后再调用console.log来输出结果。

对于对象来说,要想克隆一个对象就比较困难了。在非WebKit浏览器中调试或者编写一个复杂的克隆函数可能是最好的方法。如果你只使用简单的对象,其中键的顺序不重要且没有函数,那么你可以使用console.logSanitizedCopy函数。这个函数会先将参数转换成JSON字符串,再将其转换回对象,从而实现克隆的效果。

需要注意的是,所有这些方法都会导致性能下降,所以在调试完成后,应该及时移除这些方法。

为了解决在调试过程中console.log输出相同结果的问题,我们可以使用Array#slice方法克隆数组,或者使用自定义的console.logShallowCopy函数克隆参数。对于对象,使用console.logSanitizedCopy函数可以实现克隆。在使用完这些方法后,需要及时移除以提高性能。

0
0 Comments

为什么我在第一个和第二个console.log()中得到相同的结果?

从Eric的解释中可以得知,这是由于console.log()被排队处理,它会打印数组(或对象)的后续值。

有以下5种解决方案:

1. arr.toString() // 对于[1,[2,3]]不适用,因为它会显示1,2,3

2. arr.join() // 与上述相同

3. arr.slice(0) // 创建一个新数组,但如果arr是[1, 2, arr2, 3],并且arr2发生变化,则可能显示后续值

4. arr.concat() // 创建一个新数组,但与slice(0)相同的问题

5. JSON.stringify(arr) // 这个方法很好,它会对整个数组或对象进行快照,并以精确的结构显示

任何复制列表/对象的解决方案都可以使用。我最喜欢的浅拷贝对象的方法是在ECMAScript 2018中引入的:copy = {...orig}。值得一提的是,浅拷贝会将数组转换为对象。

0
0 Comments

为什么在第一次和第二次console.log()中得到相同的结果?

在这个问题中,有一个已知的未经确认的Webkit bug,可以解释这个问题的出现:https://bugs.webkit.org/show_bug.cgi?id=35801(已修复!)。关于这个bug有一些争论,争论的焦点在于这是否算是一个bug以及是否可以修复。对我来说,这似乎是一个不好的行为。尤其让我感到困扰的是,在Chrome中,无论控制台是否打开,只要页面刷新,这个问题就会发生,即使代码位于立即执行的脚本中(在页面加载之前)。在控制台尚未激活时调用console.log只会导致对该对象的引用被排队,而不是控制台中的输出。因此,数组(或任何对象)只有在控制台准备好之后才会被评估。这确实是一种懒惰评估。

然而,有一个简单的方法可以避免这个问题:

var s = ["hi"];

console.log(s.toString());

s[0] = "bye";

console.log(s.toString());

通过调用toString,您可以创建一个在内存中表示的表示形式,这个表示形式不会被后续语句更改,而控制台在准备好时会读取它。控制台输出与直接传递对象略有不同,但似乎可以接受:

hi

bye

实际上,对于关联数组或其他对象,这可能是一个真正的问题,因为toString不会产生任何有价值的内容。是否有一个简单的解决方案适用于一般的对象?

webkit几个月前已经解决了这个问题。

可以这样做:console.log(JSON.parse(JSON.stringify(s));

我只想提一下,在当前版本的Chrome中,控制台是延迟的,并且错误地输出值(或者它从来没有正确输出过)。例如,我在记录一个数组并在记录后弹出数组的顶部值,但它显示的是没有弹出值的数组。您的toString()建议在我需要查看值时非常有用。

还有一个很好的选择是从代码中插入一个断点,使用debugger;。如果可行的话,也可以手动从开发者工具中添加断点。

0