mozilla Mozilla Developer Network
- MDN
- Web technology For developers
- JavaScript
- Memory Management
Your Search Results
Memory Management
In This Article
- Introduction
- Memory life cycle
- Allocation in JavaScript
- Value initialization
- Allocation via function calls
- Using values
- Release when the memory is not needed anymore
- Garbage collection
- References
- Reference-counting garbage collection
- Example
- Limitation: cycles
- Real-life example
- Mark-and-sweep algorithm
- Cycles are not a problem anymore
- Limitation: objects need to be made explicitly unreachable
- See also
Introduction
Low-level languages, like C, have low-level memory management primitives like malloc()
and free()
. On the other hand, JavaScript values are allocated when things (objects, strings, etc.) are created and “automatically” freed when they are not used anymore. The latter process is called garbage collection. This “automatically” is a source of confusion and gives JavaScript (and high-level languages) developers the impression they can decide not to care about memory management. This is a mistake.
Memory life cycle
Regardless of the programming language, memory life cycle is pretty much always the same:
- Allocate the memory you need
- Use the allocated memory (read, write)
- Release the allocated memory when it is not needed anymore
The first and second parts are explicit in all languages. The last part is explicit in low-level languages, but is mostly implicit in high-level languages like JavaScript.
Allocation in JavaScript
Value initialization
In order not to bother the programmer with allocations, JavaScript does it alongside with declaring values.
var n = 123;
var s = "azerty";
var o = {
a: 1,
b: null
};
var a = [1, null, "abra"];
function f(a){
return a + 2;
}
someElement.addEventListener('click', function(){
someElement.style.backgroundColor = 'blue';
}, false);
Allocation via function calls
Some function calls result in object allocation.
var d = new Date();
var e = document.createElement('div');
Some methods allocate new values or objects:
var s = "azerty";
var s2 = s.substr(0, 3);
var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2);
Using values
Using value basically means reading and writing in allocated memory. This can be done by reading or writing the value of a variable or an object property or even passing an argument to a function.
Release when the memory is not needed anymore
Most of memory management issues come at this phase. The hardest task here is to find when “the allocated memory is not needed any longer”. It often requires for the developer to determine where in the program such piece of memory is not needed anymore and free it.
High-level languages embed a piece of software called “garbage collector” whose job is to track memory allocation and use in order to find when a piece of allocated memory is not needed any longer in which case, it will automatically free it. This process is an approximation since the general problem of knowing whether some piece of memory is needed is undecidable (can’t be solved by an algorithm).
Garbage collection
As stated above the general problem of automatically finding whether some memory “is not needed anymore” is undecidable. As a consequence, garbage collections implement a restriction of a solution to the general problem. This section will explain the necessary notions to understand the main garbage collection algorithms and their limitations.
References
The main notion garbage collection algorithms rely on is the notion of reference. Within the context of memory management, an object is said to reference another object if the former has an access to the latter (either implicitly or explicitly). For instance, a JavaScript object has a reference to its prototype (implicit reference) and to its properties values (explicit reference).
In this context, the notion of “object” is extended to something broader than regular JavaScript objects and also contains function scopes (or the global lexical scope).
Reference-counting garbage collection
This is the most naive garbage collection algorithm. This algorithm reduces the definition of “an object is not needed anymore” to “an object has no other object referencing to it”. An object is considered garbage collectable if there is zero reference pointing at this object.
Example
var o = {
a: {
b:2
}
};
var o2 = o;
o = 1;
var oa = o2.a;
o2 = "yo";
oa = null;
Limitation: cycles
There is a limitation when it comes to cycles. In the following example two objects are created and reference one another – thus creating a cycle. They will not get out of the function scope after the function call, so they are effectively useless and could be freed. However, the reference-counting algorithm considers that since each of both object is referenced at least once, none can be garbage-collected.
function f(){
var o = {};
var o2 = {};
o.a = o2;
o2.a = o;
return "azerty";
}
f();
Real-life example
Internet Explorer 6 and 7 are known to have reference-counting garbage collectors for DOM objects. Cycles are a common mistake that can generate memory leaks:
var div;
window.onload = function(){
div = document.getElementById("myDivElement");
div.circularReference = div;
div.lotsOfData = new Array(10000).join("*");
};
In the above example, the DOM element “myDivElement” has a circular reference to itself in the “circularReference” property. If the property is not explicitly removed or nulled, a reference-counting garbage collector will always have at least one reference intact and will keep the DOM element in memory even if it was removed from the DOM tree. If the DOM element holds lots of data (illustrated in the above example with the “lotsOfData” property), the memory consumed by this data will never be released.
Mark-and-sweep algorithm
This algorithm reduces the definition of “an object is not needed anymore” to “an object is unreachable”.
This algorithm assumes the knowledge of a set of objects called roots (In JavaScript, the root is the global object). Periodically, the garbage-collector will start from these roots, find all objects that are referenced from these roots, then all objects referenced from these, etc. Starting from the roots, the garbage collector will thus find all reachable objects and collect all non-reachable objects.
This algorithm is better than the previous one since “an object has zero reference” leads to this object being unreachable. The opposite is not true as we have seen with cycles.
As of 2012, all modern browsers ship a mark-and-sweep garbage-collector. All improvements made in the field of JavaScript garbage collection (generational/incremental/concurrent/parallel garbage collection) over the last few years are implementation improvements of this algorithm, but not improvements over the garbage collection algorithm itself nor its reduction of the definition of when “an object is not needed anymore”.
Cycles are not a problem anymore
In the first above example, after the function call returns, the 2 objects are not referenced anymore by something reachable from the global object. Consequently, they will be found unreachable by the garbage collector.
The same thing goes with the second example. Once the div and its handler are made unreachable from the roots, they can both be garbage-collected despite referencing each other.
Limitation: objects need to be made explicitly unreachable
Although this is marked as a limitation, it is one that is rarely reached in practice which is why no one usually cares that much about garbage collection.
See also
Document Tags and Contributors
Tags:
Contributors to this page:lleaff, rudolfo, beytek, jontejada, mbjordan, ronyeh, fscholz, mishra, macinnir, RogerPoon, xfq, bigperm, anirudh_venkatesh, Agamemnus, velvel53, hectorsan68, Nick_Pershin, Sheppy, RichardC, ethertank, maxatwork, iskitz, dbruant Last updated by:lleaff, <time>Aug 1, 2016, 1:06:43 PM</time> See also
- JavaScript
- Tutorials:
- JavaScript Guide
- Introduction
- Grammar and types
- Control flow and error handling
- Loops and iteration
- Functions
- Expressions and operators
- Numbers and dates
- Text formatting
- Regular expressions
- Indexed collections
- Keyed collections
- Working with objects
- Details of the object model
- Iterators and generators
- Meta programming
- Introductory
- JavaScript basics
- JavaScript technologies overview
- Introduction to Object Oriented JavaScript
- Intermediate
- A re-introduction to JavaScript
- JavaScript data structures
- Equality comparisons and sameness
- Closures
- Advanced
- Inheritance and the prototype chain
- Strict mode
- JavaScript typed arrays
- SIMD types
- Memory Management
- Concurrency model and Event Loop
- References:
- Built-in objects
- Array
- ArrayBuffer
- Atomics
- Boolean
- DataView
- Date
- Error
- EvalError
- Float32Array
- Float64Array
- Function
- Generator
- GeneratorFunction
- Infinity
- Int16Array
- Int32Array
- Int8Array
- [InternalError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError “The InternalError object indicates an error that occurred internally in the JavaScript engine. For example: “InternalError: too much recursion”.”)
- Intl
- Intl.Collator
- Intl.DateTimeFormat
- Intl.NumberFormat
- Iterator
- JSON
- Map
- Math
- NaN
- Number
- Object
- ParallelArray
- Promise
- Proxy
- RangeError
- ReferenceError
- Reflect
- RegExp
- [SIMD](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SIMD “SIMD (pronounced “sim-dee”) is short for Single Instruction/Multiple Data which is one classification of computer architectures. SIMD operations perform the same computation on multiple data points resulting in data level parallelism and thus performance gains, for example for 3D graphics and video processing, physics simulations or cryptography, and other domains.”)
- SIMD.Bool16x8
- SIMD.Bool32x4
- SIMD.Bool64x2
- SIMD.Bool8x16
- SIMD.Float32x4
- SIMD.Float64x2
- SIMD.Int16x8
- SIMD.Int32x4
- SIMD.Int8x16
- SIMD.Uint16x8
- SIMD.Uint32x4
- SIMD.Uint8x16
- Set
- SharedArrayBuffer
- StopIteration
- String
- Symbol
- SyntaxError
- TypeError
- TypedArray
- URIError
- Uint16Array
- Uint32Array
- Uint8Array
- Uint8ClampedArray
- WeakMap
- WeakSet
- decodeURI()
- decodeURIComponent()
- [encodeURI()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI “The encodeURI() function encodes a Uniform Resource Identifier (URI) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of two “surrogate” characters).”)
- [encodeURIComponent()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent “The encodeURIComponent() function encodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of two “surrogate” characters).”)
- escape()
- eval()
- isFinite()
- isNaN()
- null
- parseFloat()
- parseInt()
- undefined
- unescape()
- uneval()
- Array.from()
- Array.isArray()
- [Array.observe()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/observe “The Array.observe() method was used for asynchronously observing changes to Arrays, similar to Object.observe() for objects. It provided a stream of changes in order of occurrence. It’s equivalent to Object.observe() invoked with the accept type list [“add”, “update”, “delete”, “splice”]. However, this API has been deprecated and removed from Browsers. You can use the more general Proxy object instead.”)
- Array.of()
- Array.prototype
- Array.prototype.concat()
- Array.prototype.copyWithin()
- Array.prototype.entries()
- Array.prototype.every()
- Array.prototype.fill()
- Array.prototype.filter()
- Array.prototype.find()
- Array.prototype.findIndex()
- Array.prototype.forEach()
- Array.prototype.includes()
- Array.prototype.indexOf()
- Array.prototype.join()
- Array.prototype.keys()
- Array.prototype.lastIndexOf()
- Array.prototype.map()
- Array.prototype.pop()
- Array.prototype.push()
- Array.prototype.reduce()
- Array.prototype.reduceRight()
- Array.prototype.reverse()
- Array.prototype.shift()
- Array.prototype.slice()
- Array.prototype.some()
- Array.prototype.sort()
- Array.prototype.splice()
- [Array.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toLocaleString “The toLocaleString() method returns a string representing the elements of the array. The elements are converted to Strings using their toLocaleString methods and these Strings are separated by a locale-specific String (such as a comma “,”).”)
- Array.prototype.toSource()
- Array.prototype.toString()
- Array.prototype.unshift()
- Array.prototype.values()
- [Array.prototype@@iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator “The initial value of the @@iterator property is the same function object as the initial value of the values() property.”)
- Array.prototype[@@unscopables]
- Array.unobserve()
- array.length
- get Array[@@species]
- Expressions & operators
- Arithmetic operators
- Array comprehensions
- Assignment operators
- Bitwise operators
- Comma operator
- Comparison operators
- Conditional (ternary) Operator
- Destructuring assignment
- Expression closures
- Generator comprehensions
- Grouping operator
- Legacy generator function expression
- Logical Operators
- Object initializer
- Operator precedence
- Property accessors
- Spread operator
- class expression
- delete operator
- function expression
- function* expression
- in operator
- instanceof
- new operator
- new.target
- super
- this
- typeof
- void operator
- yield
- yield*
- Statements & declarations
- Legacy generator function
- block
- break
- class
- const
- continue
- debugger
- default
- do…while
- empty
- export
- for
- for each…in
- for…in
- for…of
- function
- function*
- if…else
- import
- label
- let
- return
- switch
- throw
- try…catch
- var
- while
- with
- Functions
- Arguments object
- Arrow functions
- Default parameters
- Method definitions
- Rest parameters
- getter
- setter
- arguments.callee
- arguments.caller
- arguments.length
- [arguments@@iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/@@iterator “The initial value of the @@iterator property is the same function object as the initial value of the Array.prototype.values property.”)
- Classes
- constructor
- extends
- static
- Errors
- Error: Permission denied to access property “x”
- InternalError: too much recursion
- RangeError: argument is not a valid code point
- RangeError: invalid array length
- RangeError: precision is out of range
- RangeError: radix must be an integer
- RangeError: repeat count must be less than infinity
- RangeError: repeat count must be non-negative
- ReferenceError: “x” is not defined
- ReferenceError: assignment to undeclared variable “x”
- ReferenceError: deprecated caller or arguments usage
- ReferenceError: invalid assignment left-hand side
- ReferenceError: reference to undefined property “x”
- SyntaxError: “x” is not a legal ECMA-262 octal constant
- SyntaxError: JSON.parse: bad parsing
- SyntaxError: Malformed formal parameter
- SyntaxError: Unexpected token
- SyntaxError: Using //@ to indicate sourceURL pragmas is deprecated. Use //# instead
- SyntaxError: missing ) after argument list
- SyntaxError: missing ; before statement
- [SyntaxError: missing ] after element list](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_bracket_after_list “SyntaxError.”)
- SyntaxError: missing } after property list
- SyntaxError: redeclaration of formal parameter “x”
- SyntaxError: return not in function
- SyntaxError: test for equality (==) mistyped as assignment (=)?
- SyntaxError: unterminated string literal
- TypeError: “x” has no properties
- TypeError: “x” is (not) “y”
- TypeError: “x” is not a constructor
- TypeError: “x” is not a function
- TypeError: “x” is read-only
- TypeError: More arguments needed
- TypeError: invalid Array.prototype.sort argument
- TypeError: property “x” is non-configurable and can’t be deleted
- TypeError: variable “x” redeclares argument
- Warning: -file- is being assigned a //# sourceMappingURL, but already has one
- Warning: unreachable code after return statement
- Misc
- Lexical grammar
- JavaScript data structures
- Enumerability and ownership of properties
- Iteration protocols
- Strict mode
- Transitioning to strict mode
- Template literals
- Deprecated features
- New in JavaScript
- ECMAScript 5 support in Mozilla
- [ECMAScript 6 support in Mozilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla “ECMAScript 2015 (6th Edition) is the current version of the ECMAScript Language Specification standard. Commonly referred to as “ES6”, it defines the standard for the JavaScript implementation in SpiderMonkey, the engine used in Firefox and other Mozilla applications.”)
- ECMAScript Next support in Mozilla
- Firefox JavaScript changelog
- [New in JavaScript 1.1](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.1 “The following is a changelog for JavaScript from Netscape Navigator 2.0 to 3.0. The old Netscape documentation references this as “Features added after version 1”. Netscape Navigator 3.0 was released on August 19, 1996. Netscape Navigator 3.0 was the second major version of the browser with JavaScript support.”)
- New in JavaScript 1.2
- New in JavaScript 1.3
- New in JavaScript 1.4
- New in JavaScript 1.5
- New in JavaScript 1.6
- New in JavaScript 1.7
- New in JavaScript 1.8
- New in JavaScript 1.8.1
- New in JavaScript 1.8.5
- Documentation:
- Useful lists
- All pages index
- Methods index
- Properties index
- Pages tagged “JavaScript”
- Contribute
- JavaScript doc status
- The MDN project
© 2005-2016 Mozilla Developer Network and individual contributors.
Content is available under these licenses.