Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

preface

When writing code, we often add console.log() to see if the code is executing or to print out information when it reaches a certain location to help debugging. In most cases, this is fine, but before you print a reference data type and want to view its value at a point in time through console.log(), be aware that you may not be seeing its value at that point in time.

This article is mainly in the actual use of a similar problem, because the use of small program development related software to debug the code, breakpoints are not very good (I will appear to break the point, but can not see the value of the object), so use console.log() to debug. The problem with that premise.

Problem reproduction

First of all, LET me simulate the problem I encountered:

console.log(this.list);
console.log(this.list.length)
/ /... Other code
this.list.push(1)
Copy the code

This code in developer tools will print:

Since this.list is an observable, you don’t know what’s in it until you click on it.

This makes me wonder why there are values in the array, but the printed array is 0 in length, and I did a few deletions of the array after the two console.log() and got an error.

So there were no values in the array when both console.log() were executed. I was misled by the output of console.log(). I thought that the value must be this.list at this point in time, but didn’t know that for reference data types, Console.log () is not always accurate.

Trouble spots

Use your browser to reproduce the problem:

If you click on A at this time, you will find:

There’s an extra element in a.

Evaluated upon first expanding.It may have changed since then.

The browser also notes that this value may have changed since the first validation, due to the different performance of the storage methods and console.log() that refer to the data type on different platforms.

About reference data types

In terms of reference data types, that is, objects in JS, of course, arrays and functions in JS are essentially objects. After we declare an object, we create a space in memory to hold the data

This is why shallow-copied objects share attributes:

So when we modify an object, we’re actually modifying the memory data that it points to

aboutconsole.log()

In addition, console.log() is executed differently on different platforms. For example, this problem does not occur in Node, but in Chrome, when we print a reference data type, the browser prints a snapshot of it at that time:

When you click on the object to expand again, the browser will fetch the data from memory again:

This is why the above problem occurs, because in Chrome, when you expand Object in the console, Chrome evaluates it again, this time to display its properties, so it prints differently because the value of the entity referenced by the Object has changed.

Why do browsers or developer tools behave like this?

This issue is addressed in the Asynchronous Console section of Section 1.1 of Asynchrony and Performance, Part 2 of What you Don’t Know in javascript volume:

There is no specification or set of requirements around how the console.* methods work — they are not officially part of JavaScript, but are instead added to JS by the hosting environment (see the Types & Grammar title of this book series).

So, different browsers and JS environments do as they please, which can sometimes lead to confusing behavior.

In particular, there are some browsers and some conditions that console.log(..) does not actually immediately output what it’s given. The main reason this may happen is because I/O is a very slow and blocking part of many programs (not just JS). So, it may perform better (from the page/UI perspective) for a browser to handle console I/O asynchronously in the background, without you perhaps even knowing that occurred.

Translation:

There is no specification or set of requirements that specify how the console.* family of methods should work — they are not a formal part of JavaScript, but are added to it by the host environment (see the “Types and Syntax” section of this book). Therefore, different browsers and JavaScript environments can be implemented as they wish, which can sometimes lead to confusion. In particular, under certain conditions, the console.log(..) of some browsers Incoming content is not output immediately. The main reason for this is that IN many programs (not just JavaScript), I/O is a very slow blocking part. So, (from a page /UI perspective) the browser can improve performance by asynchronously processing console I/O in the background, where the user may not even be aware of it happening.

Here’s an example:

var a = { index: 1 }; // Then console.log(a); / /?? // then a.index++;Copy the code

We usually think of it as just executing to console.log(..) Statement to see a snapshot of the a object, print something like {index: 1}, and then modify it when the next statement a.id ++ is executed strictly after the output of A.

For the most part, the object representation that the preceding code outputs in the developer tools console is as expected. However, while this code is running, the browser may think it needs to defer console I/O to the background, in which case a.index++ may have been executed by the time the browser console outputs the object’s contents, thus displaying {index: 2}.

Exactly when console I/O is delayed, or even if it can be observed, is fluid.

So if you encounter an object in console.log(..) during debugging The statement is later modified and you see unexpected results, be aware that this may be due to this I/O asynchrony.

The book recommends:

In this rare case, the best option is to use breakpoints in the JavaScript debugger rather than rely on console output. The next best option is to serialize the object into a string to force a “snapshot”, for example via json.stringify (..) .

On moreconsole.log()The implementation of the

For more information about console.log() execution, see the Node documentation. To learn more about how this works, see the Node documentation

The console console

The solution

1. Using JSON. Stringify (..) To print the data

Using JSON. Stringify (..) We convert the current object to JSON, which disassociates the object from itself and just prints it out as a string, so we can see what we want

2. 使用 ES6 的 …

You can also use {… A} this way to output

This operation essentially creates a new space for storing the printed object at the time of printing, just like a deep copy, which is a new object different from the original object.

conclusion

So console.log() may print something that is not necessarily trustworthy. It may be trustworthy for basic data types, but you need to be careful when printing a reference data type. Watch your browser to see if the data has changed later.

So generally in the case of breakpoint debugging, or breakpoint debugging is a more scientific and reliable method.