How does js run after encryption? js displays passwords and hides passwords

Hello everyone, the editor will answer the question of how js runs after encryption. Many people still don’t know how to display passwords and hide passwords in js. Let’s take a look together now!

Have you ever been asked this question in an interview: If a web page freezes, what do you think might be the reason? Is there any way to find the cause and fix it?

This is a broad and deep question that involves a lot of page performance optimization issues. I still remember how I responded to this question when asked in an interview:

  1. First, check whether there are too many network requests, resulting in slow data transmission. This problem can be optimized by caching to reduce weight of Deepl.

  2. It is also possible that the bundle of a certain resource is too large, and we can consider splitting it.

  3. Check our JavaScript code to see if there are too many loops taking too long on the main thread.

  4. Maybe the browser is rendering too many things in a certain frame.

  5. During the page rendering process, there may be a large number of repeated reflows and redraws.

  6. Maybe there’s something else, I don’t know…

Later, I realized that the long-term stuck feeling of the page may also be caused by a memory leak. In this article, I will discuss this topic with you.

What is a memory leak?

A memory leak is a failure to free memory that is no longer in use due to negligence or some programming error. Simply put, if a variable consumes 100M of memory, and you don’t need it, but, without manually or automatically releasing it, it will still consume 100M of memory. This is a waste of memory or a memory leak.

Stack memory and heap memory

JavaScript memory is divided into stack memory and heap memory. Stack memory is used for simple variables, and heap memory is used for complex objects.

Simple variables refer to primitive data types such as String, Number, Boolean, Null, Undefined, Symbol, Bigint.

Complex objects refer to reference data types, such as Object, Array, Function…

Garbage collection in JavaScript

According to the definition of memory leak, some variables or data are no longer used or needed, then it is garbage variable or garbage data. If it is kept in memory, it will eventually lead to excessive memory usage. At this time, we need to recycle these garbage data. Here, we introduce the concept of garbage collection mechanism.

Garbage collection mechanisms are divided into two categories: manual and automatic.

C and C++ use a manual recycling mechanism, that is, developers first manually allocate a certain amount of memory to a variable through code. When it is not needed, developers will use manual annotation code to release the memory.

JavaScript, on the other hand, uses automatic collection, which means we don’t care how much memory we allocate for a variable or when it is freed, because it’s all automatic. But that doesn’t mean we don’t need to care about memory management! Otherwise, the memory leak discussed in this article would not occur.

Next, let’s discuss the JavaScript garbage collection mechanism.

Generally speaking, global variables are not automatically recycled, so we will focus on local scope memory collection.

Here is a code snippet:

function fn1 () {<!-- --></code><code> let a = {<!-- --></code><code> name: 'bytefish'</code><code> }</code>
<code>let b = 3</code>
<code> function fn2() {<!-- --></code><code> let c = [1, 2, 3]</code><code> }</code>
<code>fn2()</code>
<code> return a</code><code>}</code><code>let res = fn1()

The call stack of the above code is shown below:

The left side of the picture is the stack space, which is used to store execution context and primitive type data. On the right is the heap space, used to store objects.

When the code is executed to fn2(), the execution context in the call stack from top to bottom is fn2 function execution context => fn1 function execution context => global execution context.

When function fn2 completes its internal execution, it’s time to exit the fn2 execution context by moving the arrow down. The fn2 execution context is cleared and the stack memory space is released, as shown in the following figure:

After the internal execution of function fn1 is completed, it is time to exit the fn1 function execution context, that is, the arrow moves downward again. At this time, the fn1 function execution context will be cleared and the corresponding stack memory space will be released, as shown in the figure:

At this point, our program is in the global execution context.

The JavaScript garbage collector walks through the call stack and collects garbage every once in a while. Assume that the garbage collection mechanism is triggered at this time.

When the garbage collector traverses the call stack, it finds that variables b and c are not used. Therefore, it is judged as garbage data and marked.

Because the fn1 function returns variable a after execution and stores it in the global variable res, it is identified as active data and marked accordingly.

When idle, all variables marked as garbage data will be cleared to release the corresponding memory, as shown in the figure:

Here’s a quick summary:

  1. JavaScript’s garbage collection mechanism is automated, and tags are used to identify and clean up junk data.

  2. After leaving the local scope, if the variables in the scope are not referenced by the external scope, they will be cleared later.

Observe memory usage using Chrome DevTools

Using Chrome DevTools’ Performance and Memory panels, we can observe the Memory usage of JavaScript applications, which gives us a deeper understanding of the memory management mechanism.

First, let’s prepare a simple JavaScript program:

<!DOCTYPE html></code><code><html></code><code> <body></code><code> <button onclick="myClick()">execute fn1</button ></code><code> <></code><code> function fn1() {<!-- --></code><code> let a = new Array(10000);</code><code> return a;</code><code> }</code>
<code> let res = [];</code>
<code> function myClick() {<!-- --></code><code> res.push(fn1());</code><code> }</code><code></></code><code> </body></code><code></html>

This page is very simple: there is only one button on the page, and every time we click this button, our program will create a new array and store it in the array res.

Create this file on your computer, then copy the file address and open it in Chrome:

Note in this step: Be sure to use the file address to open the file directly. Do not use VSCode or other IDE Live Server functions to open the file. The latter inserts hot update code into the file, making our memory observations inaccurate. If necessary, you should also temporarily disable browser extensions to avoid interfering with our subsequent testing.

Then, we open the Performance panel of the browser DevTools:

This panel has many functions. The gray dot above is the button that records the program’s memory usage. Click the point to start recording, then click the button to execute fn1 repeatedly to get the following content:

result:

The line chart below is the heap memory usage. We can see that every time the button is clicked, the heap memory usage will increase because our function fn1 creates a new object, and this object is stored in the array res and has not been recycled by the garbage collector.

If the line chart is trending upward and there is no sign of a callback, the program is constantly consuming memory and the program is likely to have a memory leak.

Memory Panel

The memory panel allows us to view memory usage in real time.

usage:

After we start recording, we can see that a blue histogram is generated on the right side of the figure, which represents the amount of memory under the current timeline.

Or we can open Medium’s homepage and record the histogram in the same way.

Here we can see the undulating blue and gray bars in the graph. Gray represents that the previously occupied memory space has been cleared and released.

If only blue histograms are generated in your project and never turn gray, then the memory is never freed and your program may have a memory leak.

Memory leak example

So, what are the situations in which memory leaks occur? Here are some common ones:

  • Improper use of closures

  • Unexpectedly generated global variable

  • Detached DOM nodes

  • Console printing

  • Uncleared timer

Next, walk through the scenario and try to capture the issue using the Chrome DevTools described earlier.

1. Improper use of closures

In the example at the beginning of this article, after exiting the fn1 function execution context, the variable a in that context will be collected as garbage data. But because the fn1 function finally returns variable a and assigns it to the global variable res, it generates a reference to the value of variable a, so the value of variable a is marked as active and has been occupying the corresponding memory. Assuming that the variable res is not used later, this is an example of closures being used incorrectly.

Let’s take a look at the memory leak problem caused by using Performance and Memory closures. To make the consequences of a memory leak more obvious, let’s slightly change the example at the beginning of this article. The code looks like this:

<!DOCTYPE html></code><code><html></code><code> <body></code><code> <button onclick="myClick()">execute fn1</button ></code><code> <></code><code> function fn1() {<!-- --></code><code> let a = new Array(10000);</code>
<code>let b = 3;</code>
<code> function fn2() {<!-- --></code><code> let c = [1, 2, 3];</code><code> }</code>
<code>fn2();</code>
<code> return a;</code><code> }</code>
<code> let res = [];</code>
<code> function myClick() {<!-- --></code><code> res.push(fn1());</code><code> }</code><code></></code><code> </body></code><code></html>

We have set up a button on this page, and each click will add the return value of the fn1 function to the global variable res. Next, we can record the memory curve in the Performance panel.

  • First, we click on the gray dot to start recording.

  • We then do manual garbage collection to ensure we have a stable initial memory baseline.

  • Next, we click the button several times to execute the fn1 function.

  • Finally, we do garbage collection again.

Here’s how to do it:

Results:

It can be seen from the results that after each call to function fn1, the heap memory space increases and the overall curve gradually increases. Then, after the last memory cleanup, we can find that the final curve height is higher than the baseline, indicating that there may be content leaks in the program.

When a memory leak is known to exist, we can use the Memory panel to more specifically identify and locate the problem.

Every time the button is clicked, a blue bar will appear on the dynamic memory allocation map. After we trigger garbage collection, the blue bar does not turn into a gray bar, indicating that the allocated memory has not been cleared.

We can then use the heap snapshot to find the function causing the memory leak.

By moving the cursor over the blue column we can see the objects created during this time. You can then click on the object to see the function that created the object. This function is the main culprit of memory leaks.

2. Accidentally generated global variables

I mentioned at the beginning of this article that global variables are generally not collected by the garbage collector. We should use global variables as little as possible if not necessary. Sometimes developers inadvertently throw some variables into the global world, such as assigning a value to a variable without declaring it, causing it to be created globally.

The sample code is as follows:

function fn1() {<!-- --></code><code> // `name` is not declared</code><code> name = new Array(99999999)</code><code>}</code><code>fn1()

In this case, the variable name is automatically created globally and a large array is assigned to the name. And because it is a global variable, the memory space will never be released.

Therefore, you need to pay more attention in daily coding and do not assign values before variables are declared. Or we can turn on strict mode so that when we make a mistake unknowingly, we will receive an error warning, for example:

function fn1() {<!-- --></code><code> 'use strict';</code><code> name = new Array(99999999)</code><code>}</code><code>fn1()

3. Separated DOM nodes

Let’s say you manually delete a DOM node. You should have freed the memory of the DOM node, but somehow some code is still referencing the deleted node and cannot free the memory. For example:

<!DOCTYPE html></code><code><html lang="en"></code><code><head></code><code> <meta charset="UTF-8"> </code><code> <meta http-equiv="X-UA-Compatible" content="IE=edge"></code><code> <meta name="viewport" content="width=device-width , initial-scale=1.0"></code><code> <title>Document</title></code><code></head></code><code><body></code><code> <div id="root"></code><code> <div class="child001">I am child element</div></code><code> <button>remove</button></code><code></div></code><code><></code><code> let btn = document.querySelector('button')</code><code> let child001 = document.querySelector(' .child001')</code><code> let root = document.querySelector('#root')</code>
<code> btn.addEventListener('click', function() {<!-- --></code><code> root.removeChild(child001)</code><code> })</code><code></></code>
<code></body></code><code></html>

This code will delete the contents of node .child001 when the button is clicked. Although the node is indeed removed from the DOM after clicking, the global variable child001 still has a reference to the node, so the node’s memory is not released.

We can test this using the Memory panel:

We first use the Heap Snapshot function to record the Heap memory usage at the beginning of the program, then we click the button to remove the .child001 DOM element and record the Heap memory usage again.

If we search for the detached keyword in the second snapshot, we can filter out DOM nodes that were detached from the DOM tree but not removed. Then we did find the element .child001, which means that the element has not been reclaimed by the garbage collector.

This is also a common scenario for memory leaks. The solution is shown below:

let btn = document.querySelector("button");</code><code>btn.addEventListener("click", function () {<!-- --></code><code> let child001 = document.querySelector(".child001");</code><code> let root = document.querySelector("#root");</code><code> root.removeChild(child001);</code><code>});

The change is as simple as moving the reference of the .child001 node to the callback function on the click event. Then, when we remove the node and exit the execution of the callback function, the reference to the node will be automatically cleared and no memory leak will occur.

Let’s verify this:

The result is that we can no longer find this element in the second heap snapshot, indicating that it has been collected. We successfully resolved the memory leak issue.

4.Console printing

Does console printing also cause memory leaks? Yes, if the browser doesn’t always store information about the objects we print, why do we see specific data every time we open the console? Let’s take a look at the test code:

<!DOCTYPE html></code><code><html lang="en"></code><code><head></code><code> <meta charset="UTF-8"> </code><code> <meta http-equiv="X-UA-Compatible" content="IE=edge"></code><code> <meta name="viewport" content="width=device-width , initial-scale=1.0"></code><code> <title>Document</title></code><code></head></code><code><body></code><code> <button>btn</button></code><code><></code><code> document.querySelector('button').addEventListener('click', function() {<!-- -- ></code><code> let obj = new Array(1000000)</code>
<code> console.log(obj);</code><code> })</code><code></></code>
<code></body></code><code></html>

We create a large array object in the callback event of clicking the button and print it out. And then let’s record it.

When recording begins, garbage collection is triggered to determine the baseline of the content. Then click the button multiple times, and finally trigger garbage collection again. Looking at the logging results, we see that the Heap memory curve gradually rises and eventually remains well above the initial baseline, which means that the large array object obj created on each click is saved by the browser and cannot be collected, because of the console log.

Next, delete console.log and see the results:

GIF:

result:

It can be seen that without console.log, every time obj is created, it will be destroyed immediately. Finally, when garbage collection is triggered, the new memory line is highly consistent with the original baseline, indicating that there is no memory leak.

Again, we can verify this again using Memory:

Use console.log:

Not using console.log

Quick summary: In a development environment, you can use the console to print variables for debugging purposes, but in a production environment, try not to print data from the console. So many JavaScript coding style specifications require us not to use console.log.

If you really want to print a variable, you can write:

if(isDev) {<!-- --></code><code> console.log(obj)</code><code>}

This avoids unnecessary printing of variables in production, as well as console.log, console.error, console.info, console.dir, etc., which also should not be used in production.

5. Uncleared timer

Defining a timer can also cause a memory leak if the timer is not cleared.

Take a look at a code example:

<!DOCTYPE html></code><code><html lang="en"></code><code><head></code><code> <meta charset="UTF-8"> </code><code> <meta http-equiv="X-UA-Compatible" content="IE=edge"></code><code> <meta name="viewport" content="width=device-width , initial-scale=1.0"></code><code> <title>Document</title></code><code></head></code><code><body></code><code> <button>start a timer</button></code><code><></code>
<code> function fn1() {<!-- --></code><code> let largeObj = new Array(100000)</code>
<code> setInterval(() => {<!-- --></code><code> let myObj = largeObj</code><code> }, 1000)</code><code> }</code>
<code> document.querySelector('button')</code><code> .addEventListener('click', function() {<!-- --></code><code> fn1()</code> <code> })</code><code></></code>
<code></body></code><code></html>

After we click the button, we execute function fn1. Function fn1 creates a large array largeObj. At the same time, it creates a setInterval timer. The timer’s callback simply references largeObj, so let’s take a look at its overall memory allocation:

Clicking the button will execute the fn1 function, then exit the execution context of the function, and the local variables in the function body should be cleared. However, the recorded results in the figure show that there seems to be a memory leak, that is, the final curve height is higher than the baseline height.

So use Memory again to confirm:

After clicking the button, we see a blue bar in the dynamic memory allocation graph, indicating that the browser has allocated a piece of memory for the variable largeObj. However, this memory was not released later, indicating that there is indeed a memory leak.

The reason is that largeObj is referenced in the setInterval callback, and the timer has not been cleared, so the memory of largeObj has not been released.

How do we solve this problem? Suppose we only need the timer to execute 3 times, we can change the code:

<body></code><code> <button>start a timer</button></code><code> <></code><code> function fn1() {<!-- -- ></code><code> let largeObj = new Array(100000);</code><code> let index = 0;</code>
<code> let timer = setInterval(() => {<!-- --></code><code> if (index === 3) clearInterval(timer);</code><code> let myObj = largeObj;</code><code> index + + ;</code><code> }, 1000);</code><code> }</code>
<code> document.querySelector("button").addEventListener("click", function () {<!-- --></code><code> fn1();</code><code> }); </code><code></></code><code> </body>

Then let’s test it:

It can be seen from the results of this recording that the height of the final curve is the same as the height of the initial baseline, indicating that there is no memory leak.

Conclusion

During the development of the project, if you encounter some performance problems that may be related to memory leaks, you can refer to the five situations listed in this article for troubleshooting. You will definitely be able to find the problem and provide a solution.

Although JavaScript garbage collection is automatic, we sometimes need to consider whether to manually clear memory for certain variables. For example, if you know that a variable is no longer needed in some situation, but it is referenced by an external variable and therefore cannot free the memory, you can assign null to the variable so that the memory is freed on subsequent garbage collection.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138486 people are learning the system