Javascript console.log() 显示值实际更改之前变量的更改值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11284663/
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
console.log() shows the changed value of a variable before the value actually changes
提问by Frederik H
This bit of code I understand. We make a copy of A and call it C. When A is changed C stays the same
这段代码我理解。我们复制 A 并将其称为 C。当 A 更改时,C 保持不变
var A = 1;
var C = A;
console.log(C); // 1
A++;
console.log(C); // 1
But when A is an array we have a different sitiuation. Not only will C change, but it changes before we even touch A
但是当 A 是一个数组时,我们有不同的情况。不仅 C 会改变,而且在我们接触 A 之前它就会改变
var A = [2, 1];
var C = A;
console.log(C); // [1, 2]
A.sort();
console.log(C); // [1, 2]
Can someone explain what happened in the second example?
有人可以解释第二个例子中发生了什么吗?
采纳答案by Elliot B.
Pointy's answerhas good information, but it's not the correct answer for this question.
Pointy 的回答有很好的信息,但它不是这个问题的正确答案。
The behavior described by the OP is part of a bug that was first reported in March 2010, patched for Webkit in August 2012, but as of this writing is not yet integrated into Google Chrome. The behavior hinges upon whether or not the console debug window is openor closedat the time the object literal is passed to console.log()
.
OP 描述的行为是 2010 年 3 月首次报告的错误的一部分,2012 年 8 月为 Webkit 打了补丁,但在撰写本文时尚未集成到 Google Chrome 中。该行为取决于在将对象文字传递给 时控制台调试窗口是打开还是关闭console.log()
。
Excerpts from the original bug report (https://bugs.webkit.org/show_bug.cgi?id=35801):
原始错误报告的摘录(https://bugs.webkit.org/show_bug.cgi?id=35801):
Description From mitch kramer 2010-03-05 11:37:45 PST
1) create an object literal with one or more properties
2) console.log that object but leave it closed (don't expand it in the console)
3) change one of the properties to a new value
now open that console.log and you'll see it has the new value for some reason, even though it's value was different at the time it was generated.
I should point out that if you open it, it will retain the correct value if that wasn't clear.
描述来自米奇克莱默 2010-03-05 11:37:45 PST
1) 创建一个具有一个或多个属性的对象字面量
2)console.log 该对象但保持关闭(不要在控制台中展开它)
3) 将属性之一更改为新值
现在打开那个console.log,你会看到由于某种原因它有新的值,即使它的值在它生成的时候是不同的。
我应该指出,如果您打开它,如果不清楚,它将保留正确的值。
Response from a Chromium developer:
Chromium 开发人员的回应:
Comment #2 From Pavel Feldman 2010-03-09 06:33:36 PST
I don't think we are ever going to fix this one. We can't clone object upon dumping it into the console and we also can't listen to the object properties' changes in order to make it always actual.
We should make sure existing behavior is expected though.
评论 #2 来自 Pavel Feldman 2010-03-09 06:33:36 PST
我认为我们永远不会解决这个问题。我们不能在将对象转储到控制台时克隆它,我们也不能监听对象属性的变化以使其始终真实。
我们应该确保现有的行为是预期的。
Much complaining ensued and eventually it led to a bug fix.
随之而来的是很多抱怨,最终导致错误修复。
Changelog notes from the patch implemented in August 2012 (http://trac.webkit.org/changeset/125174):
2012 年 8 月实施的补丁中的变更日志说明 ( http://trac.webkit.org/changeset/125174):
As of today, dumping an object (array) into console will result in objects' properties being read upon console object expansion (i.e. lazily). This means that dumping the same object while mutating it will be hard to debug using the console.
This change starts generating abbreviated previews for objects / arrays at the moment of their logging and passes this information along into the front-end. This only happens when the front-end is already opened, it only works for console.log(), not live console interaction.
截至今天,将对象(数组)转储到控制台将导致在控制台对象扩展时(即懒惰)读取对象的属性。这意味着在改变它的同时转储相同的对象将很难使用控制台进行调试。
此更改在记录对象/数组时开始为它们生成简短的预览,并将此信息传递到前端。这仅在前端已经打开时发生,它仅适用于 console.log(),不适用于实时控制台交互。
回答by Ka Tech
Console.log()
is passed a referenceto the object, so the value in the Console changes as the object changes. To avoid that you can:
Console.log()
传递了对对象的引用,因此控制台中的值会随着对象的变化而变化。为避免这种情况,您可以:
console.log(JSON.parse(JSON.stringify(c)))
Please be warned that if you log objects in the latest versions of Chrome and Firefox what you get logged on the console is a reference to the object, which is not necessarily the 'value' of the object at the moment in time you call
console.log()
, but it is the value of the object at the moment you open the console.
请注意,如果您在最新版本的 Chrome 和 Firefox 中记录对象,则您在控制台上记录的是对对象的引用,这不一定是您调用时对象的“值”
console.log()
,但是它是您打开控制台时对象的值。
回答by Pointy
Arrays are objects. Variables referto objects. Thus an assignment in the second case copied the reference(an address) to the array from "A" into "C". After that, both variables refer to the same single object (the array).
数组是对象。变量是指对象。因此,第二种情况下的赋值将数组的引用(地址)从“A”复制到“C”。之后,两个变量都指向同一个对象(数组)。
Primitive values like numbers are completely copied from one variable to another in simple assignments like yours. The "A++;" statement assigns a new value to "A".
像数字这样的原始值在像您这样的简单赋值中完全从一个变量复制到另一个变量。“A++;” 语句为“A”分配一个新值。
To say it another way: the value of a variable may be eithera primitive value (a number, a boolean, null
, or a string), or it may be a referenceto an object. The case of string primitives is a little weird, because they're more like objects than primitive (scalar) values, but they're immutable so it's OK to pretend they're just like numbers.
说另一种方式:一个变量的值可以是任一个原始值(数字,布尔值,null
或字符串),或者它可以是一个参考的一个对象。字符串基元的情况有点奇怪,因为它们更像是对象而不是基元(标量)值,但它们是不可变的,所以可以假装它们就像数字一样。
回答by Dmytro Shevchenko
EDIT:Keeping this answer just to preserve useful comments below.
编辑:保留此答案只是为了保留下面的有用评论。
@Esailija is actually right - console.log()
will not necessarily log the value the variable had at the time you tried to log it. In your case, both calls to console.log()
will log the value of C
aftersorting.
@Esalija 实际上是正确的 -console.log()
不一定会记录您尝试记录变量时的值。在您的情况下,两次调用都console.log()
将记录排序C
后的值。
If you try and execute the code in question as 5 separate statements in the console, you will see the result you expected (first, [2, 1]
, then [1, 2]
).
如果您尝试在控制台中将相关代码作为 5 个单独的语句执行,您将看到您期望的结果(首先是[2, 1]
,然后是[1, 2]
)。
回答by benipsen
Though it's not going to work in every situation, I ended up using a "break point" to solve this problem:
虽然它不会在所有情况下都有效,但我最终使用了一个“断点”来解决这个问题:
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'}
回答by raychz
The latest guidance from Mozilla as of 11/2019:
截至 2019 年 11 月,Mozilla 的最新指南:
Don't use
console.log(obj)
, useconsole.log(JSON.parse(JSON.stringify(obj)))
.This way you are sure you are seeing the value of
obj
at the moment you log it. Otherwise, many browsers provide a live view that constantly updates as values change. This may not be what you want.
不要用
console.log(obj)
,用console.log(JSON.parse(JSON.stringify(obj)))
。这样您就可以确定您
obj
在记录它的那一刻看到了它的价值。否则,许多浏览器会提供随着值的变化不断更新的实时视图。这可能不是您想要的。
回答by Danielozzo
The issue is present in Safari as well. As others have pointed out in this and similar questions, the console is passed a reference to the object, it prints the value of the object at the time the console was opened. If you execute the code in the console directly for example, the values print as expected. Instead of JSON stringifying, I prefer to spread arrays (e.g. in your case console.log([...C]);) and objects: the result is quite the same, but the code looks a bit cleaner. I have two VS code snippetsto share.
该问题也存在于 Safari 中。正如其他人在这个问题和类似问题中指出的那样,控制台传递了对对象的引用,它在打开控制台时打印对象的值。例如,如果您直接在控制台中执行代码,则值会按预期打印。而不是 JSON 字符串化,我更喜欢传播数组(例如,在您的情况下console.log([...C]);)和对象:结果完全相同,但代码看起来更简洁一些。我有两个VS 代码片段要分享。
"Print object value to console": {
"prefix": "clo",
"body": [
"console.log(\"Spread object: \", {...##代码##});"
],
"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: \", [...##代码##]);"
],
"description": "Prints array value instead of reference to console, to avoid console.log async update"
}
In order to get the same output as with console.log( JSON.parse(JSON.stringify(c))), you can leave out the string part if you wish. Incidentally, the spread syntaxoften saves time and code.
为了获得与console.log( JSON.parse(JSON.stringify(c)))相同的输出,您可以根据需要省略字符串部分。顺便说一句,扩展语法通常可以节省时间和代码。