[Javascript] Memory leakage, loop reference parsing, and javascript Leakage

Source: Internet
Author: User

[Javascript] Memory leakage, loop reference parsing, and javascript Leakage

Memory leakage

In javascript, we seldom focus on memory management. We create variables and use variables. It is normal for the browser to focus on these underlying details.

However, when applications become more complex and ajax-based, or users stay on a page for a long time, we may need to pay attention to some problems, such as a browser spending more than 1 GB of memory, and is constantly increasing. These problems are often caused by memory leakage.

Javascript Memory leakage

The core concept of javascript Memory Management is the concept of non-accessibility.

1. An obvious object set will be considered reachable: these objects are known to be the same as those in the room.

Including all objects referenced in the stack (including all local variables, parameters in the method being called), and any global variables.

2. objects are stored in the memory. They are reachable from the roots object through a quotor and a reference chain.


Here is a GC garbage collector in the browser, which is used to identify that useless objects are in the memory.


Garbage collection example

function Menu(title) {  this.title = title  this.elem = document.getElementById('id')}var menu = new Menu('My Menu')document.body.innerHTML = ''  // (1)menu = new Menu('His menu') // (2)


Let's take a look at the memory structure:



In step (1), Body. innerHTML is cleared, so its subnodes are also deleted because they are no longer associated.

However, this element # id is an exception. elem is associated, so this object will always exist in the memory. Of course, if you check its parentNode, you will get a null value.


Note: individual Dom elements can be stored in the memory even if their parent is removed.

In step (2), the reference window. menu is defined, so the previous menu will be automatically removed from the GC through the browser because it is no longer associated.



Cyclic reference set

Closures often cause circular references, such:

function setHandler() {  var elem = document.getElementById('id')  elem.onclick = function() {    // ...  }}

Here, this DOM element directly references an anonymous function through onclick. This function references the elem element through the external lexical environment.


(For more information, [[Scope] is the internal attribute of a function. When creating a function, the lexical environment of an external function is added to [[Scope, the scope of javascript is involved here .)

Such a memory structure will appear even if the handler function does not have any code. Some special methods such as addEventListener/attachEvent will also create a reference internally.


This handler is usually cleared when the elem dies.

function cleanUp() {  var elem = document.getElementById('id')  elem.parentNode.removeChild(elem)}

Call clearUp to delete an element from the Dom. There is still a reference here, LexialEnvironment. elem, but there is no nested functions, so LexialEnvironment can be recycled.

After that, elem becomes unrelated and is recycled together with its handlers.


Memory leakage

Memory leakage occurs mainly when some browsers cannot remove useless objects from the memory due to some problems.

This may occur due to some reasons, such as the browser Bugs, the browser expansion problem, more or less, our own code error.


Memory leakage of DOM-JS below IE 8

The browser before IE8 cannot clear the circular references between DOM and javascript. This problem is more serious in versions earlier than ie6 windows xp sp3.

Because the memory cannot be released before the page is detached.


So setHandler leaks the browser before ie 8, and elem and these closures cannot be cleared.

function setHandler() {  var elem = document.getElementById('id')  elem.onclick = function() { /* ... */ }}


This phenomenon exists not only in DOM elements, including XMLHttpRequest or other COM objects.

Methods used to break the circular reference in IE:




We defined elem = null, so this handler is no longer associated with DOM elements, and this loop naturally breaks.


XmlHttpRequest memory management and leakage

The following code exposes the memory of the i9 Browser:

var xhr = new XMLHttpRequest() // or ActiveX in older IExhr.open('GET', '/server.url', true)xhr.onreadystatechange = function() {  if(xhr.readyState == 4 && xhr.status == 200) {                // ...  }}xhr.send(null)

Take a look at the memory structure:



This asynchronous xmlHttpRequest object has been tracked by the browser because an internal reference is associated with it.

After the request ends, the reference will be deleted, so xhr becomes an unassociated object. This is not the case for browsers under ie9.

Fortunately, it is very easy to fix this Bug. We need to delete this xhr from this closure and use it to use this in this handler function. As follows:

var xhr = new XMLHttpRequest()  xhr.open('GET', 'jquery.js', true)  xhr.onreadystatechange = function() {  if(this.readyState == 4 && this.status == 200) {                document.getElementById('test').innerHTML++  }}   xhr.send(null)xhr = null}, 50)


In this way, there is no circular reference.


SetInterval/setTimeout

When setTimeout/setInterval is used, internal references will also exist and the tracing will know the end, and then clear up.


The setInterval end occurs in clearInterval, which may cause memory leakage. When this method does not actually do anything, the interval is not cleared.


Memory leakage size

The size of the data structure leaked by memory may not be large.

However, this closure will cause all the variables of the external function to be left behind when the internal function is active.

Therefore, you can imagine that you have created a function and a variable contains a large string.

function f() {  var data = "Large piece of data, probably received from server"  /* do something using data */  function inner() {    // ...  }  return inner}

While the function inner function stays in memory, then the LexicalEnvironment with a large variable inside will hang in memory until the inner function is alive.

In fact, this may not be leaked, and many fucntions may be created for some reasonable reasons. For example, for each request, it is not clear because they are some processing functions or something else.


If this data is only used in an external function, we can invalidate it in an external method.

function f() {  var data = "Large piece of data, probably received from server"  /* do something using data */  function inner() {    // ...  }data = null  return inner}


Now. This data is still stored in the memory as an attribute of the lexical environment, but it does not need to occupy too much space.


JQuery Memory leakage and Prevention

JQuery uses $. data to prevent ie 6 7 Memory leakage. Unfortunately, it causes some special memory leakage of jQuery.

The core principle about $. data is that any javascript entity is limited to read an element using the following method:

// works on this site cause it's using jQuery$(document.body).data('prop', 'val') // setalert( $(document.body).data('prop') ) // get

JQuery $ (elem). data (prop, val) follow these steps:

Element 1 gets a unique Tag if it does not exist:

elem[ jQuery.expando ] = id = ++jQuery.uuid  // from jQuery source

2 data is set to a special object jQuery. cache:

jQuery.cache[id]['prop'] = val

When this date is read from an element:

1 The unique identifier of this element will be returned: id = elem [jQuery. expando]

2. This data will be read from jQuery. cache [id]


JQuery sets this api to prevent DOM elements from directly referencing Javascript elements. It uses a quantity, but is safe.

This data is stored in jQuery. cache. The internal event handler function also uses the $. data API.

At the same time, it also has another impact. An element cannot be removed from the DOM and used for local calls.


The following code causes memory leakage in all browsers:

$('<div/>')  .html(new Array(1000).join('text')) // div with a text, maybe AJAX-loaded  .click(function() { })  .appendTo('#data')document.getElementById('data').innerHTML = ''

This leakage occurs because elem is removeed by clearing the innerHTML of the parent. However, this data is still stored in jQuery. cache.

More importantly, this event handler function references elem, so this event handler function and elem are retained in memory and throughout the closure.


A simple example of Leakage

function go() {  $('<div/>')    .html(new Array(1000).join('text'))     .click(function() { })}

The problem with this example is that this element is created but not used. So after this function is defined, this reference disappears, but this jQuery. cache still exists.


----------------------------------------------------------------------------

Address: http://javascript.info/tutorial/memory-leaks

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.