Memory leakage in Javascript

Source: Internet
Author: User
Recently, my Firefox often suffers from memory overflow when calling JS scripts, which leads to a false death. Today, I am fortunate enough to read this article on the IBM website. Now I am learning about Js, after reading the code, I think the writing is very good. I mentioned a lot of errors that are easy to cause when writing JavaScript code. I will share this article with you!

Internet Explorer and Mozilla Firefox are two browsers most closely related to memory leaks in JavaScript. The "culprit" of these problems in two browsers is the component object model used to manage DOM objects. Both Windows COM and Mozilla's XPCOM use reference counting garbage collection for memory allocation and retrieval. The reference count is not always compatible with the tag-cleanup type garbage collection for JavaScript. This article focuses on how to deal with Memory leakage in JavaScript code.

Memory leakage in Javascript

Javascript is a garbage collection language, which means that the memory is allocated to the object based on the object creation and will be reclaimed by the browser when no reference is made to the object. The garbage collection mechanism of JavaScript is no problem, but the browser is somewhat different in the way of allocating DOM objects and Restoring memory.

Both Internet Explorer and Mozilla Firefox use reference count to process memory for DOM objects. In the reference counting system, each referenced object retains a count to learn how many objects are referencing it. If the count is zero, the object will be destroyed and the occupied memory will be returned to the heap. Although this solution is still effective in general, there are some blind spots in circular references.

What are the problems with circular references?

When two objects reference each other, a circular reference is formed. The reference count value of each object is assigned 1. In a pure garbage collection system, loop reference is not a problem: if one of the two objects involved is referenced by any other object, both objects will be collected by garbage collection. In the reference counting system, neither of these two objects can be destroyed because the reference counting cannot be zero. In a hybrid system that uses both garbage collection and reference count, leakage occurs because the system cannot correctly identify cyclic references. In this case, neither the DOM object nor the JavaScript Object can be destroyed. Listing 1 shows a circular reference between a JavaScript Object and a DOM object.

Listing 1. Loop reference causes memory leakage

<HTML>
<Body>
<SCRIPT type = "text/JavaScript">
Document. Write ("circular references between JavaScript and Dom! ");
VaR OBJ;
Window. onload = function (){
OBJ = Document. getelementbyid ("divelement ");
Document. getelementbyid ("divelement"). expandoproperty = OBJ;
OBJ. bigstring = new array (1000). Join (new array (2000). Join ("XXXXX "));
};
</SCRIPT>
<Div id = "divelement"> Div element </div>
</Body>
</Html>

As shown in the above list, JavaScript Object OBJ has a reference to the DOM object, which is expressed as divelement. The DOM object has reference to this JavaScript Object, represented by expandoproperty. It can be seen that a circular reference is generated between a JavaScript Object and a DOM object. Because DOM objects are managed by reference count, neither of them can be destroyed.

Another memory leakage Mode

In Listing 2, create a circular reference by calling the external function myfunction. Similarly, circular references between JavaScript objects and DOM objects may cause memory leakage.

List 2. Memory leakage caused by external function calls

<HTML>
<Head>
<SCRIPT type = "text/JavaScript">
Document. Write ("Object s between JavaScript and Dom! ");
Function myfunction (element)
{
This. elementreference = element;
// This code forms a circular reference here
// By Dom --> JS --> dom
Element. expandoproperty = this;
}
Function leak (){
// This code will leak
New myfunction (document. getelementbyid ("mydiv "));
}
</SCRIPT>
</Head>
<Body onload = "leak ()">
<Div id = "mydiv"> </div>
</Body>
</Html>

As shown in the two sample codes, circular references are easy to create. Loop references are particularly prominent in one of the most convenient programming structures of javascript: closures.

Closure in Javascript

Javascript allows nested functions. A nested internal function can inherit the parameters and variables of an external function and is private to the external function. Listing 3 shows an example of an internal function.


Listing 3. An internal function

Function parentfunction (parama)
{
VaR A = parama;
Function childfunction ()
{
Return A + 2;
}
Return childfunction ();
}

Javascript developers use internal functions to integrate small practical functions into other functions. As shown in listing 3, this internal function childfunction can access the variables of the external function parentfunction. When an internal function obtains and uses the variables of its external function, it is called a closure.

Understanding closures

Consider the code snippets shown in Listing 4.

Listing 4. A simple closure

<HTML>
<Body>
<SCRIPT type = "text/JavaScript">
Document. Write ("Closure demo !! ");
Window. onload =
Function closuredemoparentfunction (parama)
{
VaR A = parama;
Return function closuredemoinnerfunction (paramb)
{
Alert (a + "" + paramb );
};
};
VaR x = closuredemoparentfunction ("outer X ");
X ("inner X ");
</SCRIPT>
</Body>
</Html>

In the above list, closuredemoinnerfunction is an internal function defined in the parent function closuredemoparentfunction. When closuredemoparentfunction is called using external X, the external function variable A is assigned an external x value. The function returns a pointer to the internal function closuredemoinnerfunction, which is included in variable X.

The local variable A of the external function closuredemoparentfunction still exists even when the external function returns. This is different from a programming language like C/C ++. in C/C ++, once the function returns, the local variable will no longer exist. In JavaScript, when closuredemoparentfunction is called, the range object with attribute a will be created. This attribute includes the value parama, also known as "external X ". Similarly, when closuredemoparentfunction returns, it returns the internal function closuredemoinnerfunction, which is included in variable X.

Because the internal function holds reference to the variables of the external function, the range object with attribute a will not be garbage collected. When you call X with the inner x parameter, that is, x ("inner X"), a warning message is displayed, indicating "outer x innerx ".

Listing 4 briefly explains the Javascript closure. Closures are very powerful because they allow internal functions to retain access to the variables of this external function when the external function returns. Unfortunately, closures are very easy to hide circular references between JavaScript objects and DOM objects.

Closures and circular references

In listing 5, you can see a closure where the JavaScript Object (OBJ) contains references to the DOM object (referenced by ID "element ). DOM elements have references to JavaScript obj. In this way, the circular reference between the created JavaScript Object and the DOM object will cause memory leakage.

Listing 5. Memory leakage mode caused by event processing

<HTML>
<Body>
<SCRIPT type = "text/JavaScript">
Document. Write ("rogram to revoke strate memory leak via closure ");
Window. onload = function outerfunction (){
VaR OBJ = Document. getelementbyid ("element ");
OBJ. onclick = function innerfunction (){
Alert ("Hi! I will leak ");
};
OBJ. bigstring = new array (1000). Join (new array (2000). Join ("XXXXX "));
// This is used to make the leak significant
};
</SCRIPT>
<Button id = "element"> click me </button>
</Body>
</Html>

Avoid Memory leakage

Fortunately, memory leakage in javascript can be avoided. After you have determined the patterns that can cause cyclic reference, as we have done in the previous sections, you can start to deal with these patterns. Here, we will take the memory leakage mode caused by event processing as an example to demonstrate three methods to deal with known memory leaks.

One solution to address memory leakage in listing 5 is to leave this JavaScript Object OBJ empty, which explicitly breaks this circular reference, as shown in Listing 6.

Listing 6. Breaking circular references

<HTML>
<Body>
<SCRIPT type = "text/JavaScript">
Document. Write ("avoiding memory leak via closure by breaking the Circular
Reference ");
Window. onload = function outerfunction (){
VaR OBJ = Document. getelementbyid ("element ");
OBJ. onclick = function innerfunction ()
{
Alert ("Hi! I have avoided the leak ");
// Some logic here
};
OBJ. bigstring = new array (1000). Join (new array (2000). Join ("XXXXX "));
OBJ = NULL; // This breaks the circular reference
};
</SCRIPT>
<Button id = "element"> "Click here" </button>
</Body>
</Html>

Listing 7 is to avoid circular references between JavaScript objects and DOM objects by adding another closure.

Listing 7. Add another Closure

<HTML>
<Body>
<SCRIPT type = "text/JavaScript">
Document. Write ("avoiding a memory leak by adding another closure ");
Window. onload = function outerfunction (){
VaR anotherobj = function innerfunction ()
{
// Some logic here
Alert ("Hi! I have avoided the leak ");
};
(Function anotherinnerfunction (){
VaR OBJ = Document. getelementbyid ("element ");
OBJ. onclick = anotherobj })();
};
</SCRIPT>
<Button id = "element"> "Click here" </button>
</Body>
</Html>

In listing 8, another function is added to avoid the closure and prevent leakage.

Listing 8. Avoid closure itself

<HTML>
<Head>
<SCRIPT type = "text/JavaScript">
Document. Write ("avoid leaks by avoiding closures! ");
Window. onload = function ()
{
VaR OBJ = Document. getelementbyid ("element ");
OBJ. onclick = doesnotleak;
}
Function doesnotleak ()
{
// Your logic here
Alert ("Hi! I have avoided the leak ");
}

</SCRIPT>
</Head>
<Body>
<Button id = "element"> "Click here" </button>
</Body>
</Html>

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.