Javascript console.log()显示变量值实际更改之前的更改值
这段代码我理解。我们复制了一份a,并称之为C。当a改变时,C保持不变Javascript console.log()显示变量值实际更改之前的更改值,javascript,google-chrome,variables,Javascript,Google Chrome,Variables,这段代码我理解。我们复制了一份a,并称之为C。当a改变时,C保持不变 var A = 1; var C = A; console.log(C); // 1 A++; console.log(C); // 1 但是当A是一个数组时,我们有一个不同的位置。不仅C会改变,而且在我们接触A之前它也会改变 var A = [2, 1]; var C = A; console.log(C); // [1, 2] A.sort(); console.log(C); // [1, 2] 有人能解释一下第二个
var A = 1;
var C = A;
console.log(C); // 1
A++;
console.log(C); // 1
但是当A是一个数组时,我们有一个不同的位置。不仅C会改变,而且在我们接触A之前它也会改变
var A = [2, 1];
var C = A;
console.log(C); // [1, 2]
A.sort();
console.log(C); // [1, 2]
有人能解释一下第二个例子中发生了什么吗?数组是对象。变量指的是对象。因此,第二种情况下的赋值将数组的引用A地址从A复制到C。之后,两个变量都引用同一个对象数组
像数字这样的基本值在像您这样的简单赋值中完全从一个变量复制到另一个变量。A++;语句将一个新值赋给
换一种说法:变量的值可以是原语值、数字、布尔值、null或字符串,也可以是对对象的引用。字符串原语的情况有点奇怪,因为它们更像对象而不是原语标量值,但它们是不可变的,所以可以假装它们像数字。编辑:保留此答案只是为了保留下面有用的注释
@Esailija实际上是对的-console.log不一定会记录您尝试记录变量时该变量的值。在您的情况下,对console.log的两个调用都将在排序后记录C的值
如果您尝试在控制台中以5条独立语句的形式执行相关代码,您将首先看到预期的结果[2,1],然后是[1,2]。虽然并非在所有情况下都有效,但我最终使用断点来解决此问题:
mysterious = {property:'started'}
// prints the value set below later ?
console.log(mysterious)
// break, console above prints the first value, as god intended
throw new Error()
// later
mysterious = {property:'changed', extended:'prop'}
有很好的信息,但这不是这个问题的正确答案
OP描述的行为是2010年3月首次报告的bug的一部分,该bug于2012年8月针对Webkit进行了修补,但截至本文撰写之时,尚未集成到Google Chrome中。行为取决于对象文本传递到console.log时控制台调试窗口是否打开或关闭
原始错误报告的摘录:
米奇·克莱默描述2010-03-05 11:37:45太平洋标准时间
1创建具有一个或多个属性的对象文字
2 console.log该对象,但将其关闭不要在控制台中展开
3将其中一个属性更改为新值
现在打开console.log,您将看到它由于某种原因具有新值,即使它在生成时的值不同
我应该指出,如果你打开它,如果不清楚,它将保留正确的值
铬开发商的回应:
帕维尔·费尔德曼2010-03-09 06:33:36太平洋标准时间评论2
我想我们永远也修不好这个。我们不能在将对象转储到控制台时克隆它,也不能监听对象属性的更改以使其始终成为现实
我们应该确保现有的行为是预期的
很多抱怨接踵而至,最终导致了错误修复
2012年8月实施的补丁中的Changelog注释:
从今天起,将对象数组转储到控制台将导致对象的属性被删除
在控制台对象扩展时读取,即延迟读取。这意味着在
使用控制台进行调试将很困难
此更改将在对象/数组开始预览时开始为其生成缩写预览
记录并将此信息传递到前端。只有在前端
已打开,它仅适用于console.log,不适用于实时控制台交互
向Console.log传递对对象的引用,因此控制台中的值会随着对象的更改而更改。为了避免这种情况,您可以:
console.log(JSON.parse(JSON.stringify(c)))
:
请注意,如果您在最新版本的Chrome和Firefox中记录对象,那么您在控制台上记录的是对该对象的引用,它不一定是您调用console.log时该对象的“值”,而是您打开控制台时该对象的值
这个问题也出现在Safari中。正如其他人在本问题和类似问题中指出的,控制台被传递到对象的引用,它在打开控制台时打印对象的值。例如,如果您直接在控制台中执行代码,则会按预期打印值。 与JSON字符串化不同,我更喜欢扩展数组,例如在您的案例控制台中;和对象:结果完全相同,但代码看起来更干净一些。我有两个要分享
"Print object value to console": {
"prefix": "clo",
"body": [
"console.log(\"Spread object: \", {...$0});"
],
"description": "Prints object value instead of reference to console, to avoid console.log async update"
},
"Print array value to console": {
"prefix": "cla",
"body": [
"console.log(\"Spread array: \", [...$0]);"
],
"description": "Prints array value instead of reference to console, to avoid console.log async update"
}
为了获得与console.log JSON.parseJSON.stringifyc相同的输出,如果愿意,可以省略字符串部分。顺便说一句,通常可以节省时间和代码。自2021年5月起的最新指南:
不要使用console.logobj,请使用console.logJSON.pa
rseJSON.stringifyobj
通过这种方式,您可以确保在记录obj时看到它的值。否则,许多浏览器会提供实时视图,随着值的变化而不断更新。这可能不是你想要的
我不认为这真的会发生。如果是这样,那是因为console.log的工作方式有时很奇怪——有时它与代码执行不完全同步。@那么,您如何解释在调用.sort之前元素的顺序发生了变化?我不知道;我现在就去试试。当我尝试编辑时,它显示数组中的值在排序之前和之后实际上是不同的。换句话说,在排序之前记录C[0]显示为2,在排序之后记录C[0]显示为1。google chrome不会记录对象在被记录时的状态。在ie9或firefox控制台中运行它。如果您想知道在它发生之前是否可以观察到排序,请在日志记录时对数组进行浅克隆。您将看到实际结果。console.logC.slice;排序;console.logC;不要过分信任数据的控制台表示。它们并不完美。@FrederikH实际上你所描述的是一个已知的bug,它是在2012年8月为Webkit修补的,但还没有进入谷歌Chrome。有关详细信息,请参见我的答案。另请参见或查看更著名的可能使用console.table?因此无法将数组打印到控制台,修改数组,然后打印修改后的版本?@Nate是的,有;我不确定我的答案中有什么让人困惑。原始问题中的第二个示例可能是console.log工作方式中固有延迟的副作用。根据我的经验,Chrome的开发者控制台在这方面是最有问题的。对不起,我误解了最初的问题。我遇到的问题是,当我打印出一个数组时,使用splice删除元素,然后再次打印出来,即使第一个print语句在拼接之前,拼接版本也会同时打印出来。我应该更仔细地阅读OP的问题。@Nate好的-以我的经验,Chrome是最糟糕的。我从来没有找到一种让它表现得更好的方法,但我也没有真正尝试过。尽管已经“修复”,但这个问题仍然在我身上发生,无论是在Chrome 46.0.2490.86中,还是在Qt的WebKit Qt 5.5中。当对象的记录值在您身上发生更改时,会非常混乱。现在,我想我可以通过每次打印对象时对其进行深度复制来避免这个问题。它在Webkit中已修复,但尚未在Chrome中进行修复。Chrome大约是在补丁推出的时候从Webkit派生出来的。因此,开发人员不能只打印所涉及的对象或数组,而必须找到一种冗长的方式在打印时打印该对象或数组的内容,仅仅是因为Chrome开发者太固执而无法实现这个补丁?完全疯了!据我所知,在最新的Firefox53中,这也是一个问题。如果您试图查看的对象要求您单击“展开”以查看其属性,则控制台输出将显示更新的变量,即使您在进行更改之前记录了该变量。例如:let test=[{a:1},{b:2}];控制台日志测试;试验[0].xxx=100;console.logtest;。“截至今天”部分实际上应该放在第一位。这对我很有用。对调试有很大帮助。只是好奇,这是否会在我每次登录时创建一个新对象?它基本上是克隆对象的当前状态,对吗?我想知道如果我在投入生产之前忘记删除这些日志函数,从长远来看是否会有影响。@pokken是的,这只会创建对象的字符串副本。我不明白为什么在进入prod console.log=function{}时,离开日志函数会产生不利影响;将此项添加到生产时的index.html,它将完全禁用console.log@伯肯特汉克斯!啊,用javascript做一些基本的事情而不伤自己的脚的样板文件太多了……这看起来很尴尬,但很有效!泰