Skip to content

Przemysław Konieczniak - Dev Notes

Memory Management - part1

JavaScript, Node.js

Introduction

This note is an introduction to the memory management topic in JavaScript language.

This part will explain the basic terms like memory management and differences between primitives and references data structure.

Memory Management

Memory Management - A form of resource management applied to computer memory. Memory management resides in hardware, in the operating system, and in programs and applications. In the application layer, this process applies to control and coordinating the way a software accesses computer memory.

The applications need access to the computer RAM (Random-access memory) to perform operations like storing values and data structures that are used during program execution and loading the bytecode that needs to be executed.

The responsibility of memory management in JavaScript takes the JavaScript engine. There are several JavaScript engines.

  • V8 - Used in Node.js and in Google Chrome browser, it is the most popular JavaScript engine
  • SpiderMonkey - The engine used in Firefox
  • Chakra - used in Microsoft Edge

When the variable is declared by the program, some chunk of memory is allocated. There are two types of memory allocation: stack memory and heap memory.

The role of the JavaScript Engine is to determine if the value is a primitive or reference value. Depending on it, the value will be stored on the stack or in the heap.

Primitives

In JavaScript are 6 primitive data types:

  • string (in opposite to other programming languages, JavaScript tracts strings as primitive data type)
  • number
  • boolean
  • symbol
  • null
  • undefined

Primitive types are simple atomic pieces of data, they do not contain both methods and properties and they are immutable (cannot be altered but can be reassigned) and they are stored on the stack. Access to the primitives is via value, that means, when you working with them you are manipulating the actual value stored in a variable.

1let foo = 'foo'
2foo.bar = 'bar'
3console.log(foo.bar) // undefined
4
5foo.repeat(2) // primitive boxing
6console.log(foo) // foo
7
8foo = foo.repeat(2)
9console.log(foo) // foofoo

There are several options to create primitive values, but the most common and also recommended is using literals. Literals in programming represent a value written exactly as it's meant to be interpreted.

1let x = 5
2x = 'foo'
3
4// object literal
5const foo = { foo: 'foo', bar: 'bar'}

The other way to create the primitives is by using the constructor function without new keyword. This way is mostly used to casting values.

1let x = '5'
2x = Number(x)
3
4const y = Boolean(null)

The last way to create literals is by using constructors and then manually unboxing the primitive value from the object. This way is not recommended and it may lead to unexpected results.

1const foo = new String('foo')
2console.log(typeof foo) // object
3
4console.log(foo.valueOf()) // 'foo'
5console.log(typeof foo.valueOf()) // 'string'

Boxing variables takes place automatically and there is no need to box variables manually.

1const foo = 'foo'
2console.log(foo.length) // 3 -> In this case string primitive was boxed on the fly by the String object.

Objects

In JavaScript, everything that is not a primitive value is an object. Objects are reference values that may be made up of multiple variables. Objects are a more complex data structure than primitives and can be seen as a collection of properties. Nearly all objects in JavaScript are instances of Object. Objects are stored in the heap. Access to the objects is via reference.

Built-in objects:

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error

Examples:

1const foo = () => {}
2const bar = { bar: 'bar' }
3const baz = [1, "2", null]
4const ban = new Set([1, 2, 3])
5const qux = new Map([['foo', 'bar']])

Objects in opposite to the primitives are mutable.

1const foo = { bar: 'foo' }
2foo.bar = 'bar'
3foo.baz = 'baz'
4
5console.log(foo.bar) // 'bar'
6console.log(foo.baz) // 'baz
7
8const bar = [1, 2, 3]
9bar.reverse()
10
11bar // [3, 2, 1]

Objects can be created by using the literals form and also by using constructors.

1let obj = {
2 foo: 'foo',
3 bar: function () {
4 return this.foo
5 }
6}
7
8let obj = new Object({
9 foo: 'foo',
10 bar: function () {
11 return this.foo
12 }
13})
14
15let obj = new Object()
16obj.foo = 'foo'
17obj.bar = function () { return this.foo }

Argument Passing

In JavaScript all arguments passed to the function are passed by value.

1const x = 10
2
3function increment (number) {
4 number += 1
5 return number
6}
7
8console.log(x) // 10
argument passing primitives

In the above example, we are passing to the function primitive value. Function increment takes as an argument the value which is a number 10. In the function scope, it is created a new variable with value 10 then it is incremented and returned. The variable x wasn't changed.

1const x = { name: 'James', age: 40 }
2
3function rename (person) {
4 person.name = 'Jack'
5 return person
6}
7
8console.log(person.name) // Jack
argument passing references

In this example, we are also passing to the function value, but in this case, the value of the variable x is a reference. When the person variable is created in the scope of rename function it indicates the same object as variable x. As a result the object x will be changed.

Copying Values

The same rule as in argument passing applies to the copying values. Primitives values are copied without side effects. When the objects are copied their value is a reference to the object on the heap.

1let x = 10
2let y = x
3let z = y
4
5x += 10
6
7x // 20
8y // 10
9z // 10
copying primitives
1const x = { foo: 'foo', bar: 'bar' }
2const y = x
3const z = y
4
5delete x.foo
6
7x // {bar: "bar"}
8y // {bar: "bar"}
9z // {bar: "bar"}
copying references

Summary

This note covers basics information about memory management in JavaScript. It was explained what is memory management, differences between the primitives, and references values.

In the next note with this series will be covered differences between the stack and heap.

© 2020 by Przemysław Konieczniak - Dev Notes. All rights reserved.