preface

In JavaScript, its memory is divided into three types: code space, stack space, and heap space, where code space is used to hold executable code.

This article gives you an in-depth understanding of stack space and heap space (heap memory and stack memory). Interested developers are welcome to read this article.

Understanding data types

The latest ECMAScript standard defines nine data types:

  • 6 kinds ofThe original type, the use oftypeofOperator check
    • undefined:typeof instance === "undefined"
    • boolean:typeof instance === "boolean"
    • number:typeof instance === "number"
    • string:typeof instance === "string
    • bigInt:typeof instance === "bigint"
    • symbol :typeof instance === "symbol"
  • null:typeof instance === "object"
  • object:typeof instance === "object"The special non-data structure type of any constructor object instance, also used as a data structure: newObject, newArray, newMap, newSet, newWeakMap, newWeakSet, newDate, and almost everything goes throughnewKeywords create things.
  • function: non-data structure, although typeof operations result in:typeof instance === "function". This result is a special abbreviation for Function, although each Function constructor is derived from the Object constructor.

The sole purpose of the Typeof operator is to check data types. If we want to check any structural types derived from Object, using Typeof won’t work because we always get “Object”. An appropriate way to check an Object class is to use the instanceof keyword. But even that is a margin of error.

Dynamic type

JavaScript is a weakly typed or dynamic language. We do not need to declare the type of the variable in advance, the type will be determined automatically during program execution. This also means that we can use the same variable to hold different types of data:

var info = "String type"; / / type string
info = 20; / / number type
info = true; / / a Boolean type
Copy the code

Implicit conversion

  • +and-Operator conversion
console.log("20" + 6) // "206" string splicing string + number = string
console.log("16" - 6) // 10 subtraction string number = number
Copy the code
  • Comparison operator
// == (equal to), the data type is automatically converted and then compared
// === (strictly equal), does not automatically convert the data type, if the data type is inconsistent, return false; If so, compare.
false= =0; // true
false= = =0; // false
undefined= =null; // undefined is a subset of null.

Copy the code
  • NaN (Not a Number) This particular Number is Not equal to all other values, including itself:
NaN= = =NaN; // false
isNaN(NaN);  // true (isNaN() is used to judge NaN)
Copy the code
  • Floating-point equality comparison
1 / 3= = = (1 - 2 / 3); // false
Floating-point numbers produce errors because computers cannot accurately represent infinite repeating decimals. To compare two floating point numbers for equality, you can only calculate the absolute value of their difference to see if it is less than a certain threshold
Math.abs(1 / 3 - (1 - 2 / 3))"0.0000001; // true
Copy the code

Packaging object

In JavaScript, everything is an object. Array and Function are essentially objects, and even values of the three primitive types — Number, String, and Boolean — are automatically converted to objects under certain conditions, that is, wrapper objects of primitive types.

In general, only objects can read and write properties, but a lot of the string methods and properties that we use in our daily lives are through. Operator to access, for example:

console.log("The Amazing Programmer.".length);
console.log("I am Baymax.".indexOf("White"));
Copy the code

As shown in the above code, when we call these methods and properties, JS has already implicitly created a wrapper object for us. The above code is handled at runtime like this:

console.log(new String("The Amazing Programmer.").length);
console.log(new String("I am Baymax.").indexOf("White"));
Copy the code

The wrapper objects implicitly created by the browser are not exactly equal to the wrapper objects explicitly created by us. Here’s an example:

var name =  "The Amazing Programmer.";
var info = new String("The Amazing Programmer.");
console.log(name == info);    // true
console.log(name === info);   // false
Copy the code

The running results are as follows:

Type test

Next, we will learn several common type detection methods in JS.

The typeof operator

Typeof detects the data types of variables and returns the following six strings: number, String, Boolean, object, undefined, and function

Let’s take an example:

var age = 1;
console.log(typeof age);  // number

var info = undefined;
console.log(typeof info);  // undefined

var title = null;
console.log(typeof title);  // object, (null is an empty object reference/or pointer).

var obj = new Object(a);console.log(typeof obj);  // object

var arr = [1.2.3];
console.log(typeof arr);  // object 

var fn = function(){}
console.log(typeof fn);  // function
Copy the code

The running results are as follows:

The instanceof operator

  • Instanceof, which checks whether an object’s prototype chain contains the prototype property of a constructor.

  • Instanceof works with detection objects and operates based on prototype chains.

  • instanceofExcept applicable to anyobjectIn addition to type checking, it can also be used to detect built-in objects, such as:Array,RegExp,Object,Function
  • instanceofBasic data type detection does not work, mainly because there is no prototype chain for basic data types.

Let’s take an example:

console.log([1.2.3] instanceof Array); // true
console.log(/abc/ instanceof RegExp); // true
console.log({} instanceof Object); // true
console.log(function() {} instanceof Function); // true
Copy the code

The running results are as follows:

The constructor property

The constructor property determines the current object’s constructor.

var o = new Object(a);console.log(o.constructor == Object); // true
var arr = new Array(a);console.log(arr.constructor == Array); // true
Copy the code

The running results are as follows:

HasOwnProperty properties

To determine whether an attribute exists in the current object instance (instead of the prototype object), let’s use an example:

const info = { title: "Book".name: "White" };
console.log(info.hasOwnProperty("title")); // true
Copy the code

The running results are as follows:

Stack memory space

Next, let’s look at what heap and stack memory space is.

Stack memory space

As the name implies, stack memory space is the space allocated in memory using the stack as a data structure.

For developers unfamiliar with stack data structures, please refer to my other article: Data Structures: Stacks and queues.

Let’s review the characteristics of the stack:

  • Last in, first out, the last element added to the stack goes out first.
  • To access the bottom element on the stack, you must remove the element above it.

Let’s draw a diagram to illustrate the stack, as follows:

Heap memory space

Similarly, as the name implies, heap memory space is the space allocated in memory using the heap as a data structure.

For developers unfamiliar with data structures like heaps, please refer to my other two articles: Data Structures: Heaps and Implementing binary heaps

In general, we refer to binary heaps as data structures. Let’s review the characteristics of binary heaps:

  • It’s a complete binary tree
  • A binary heap is either the smallest heap or the largest heap

Let’s draw a graph to show the maximum heap and minimum heap, as follows:

The relationship between variable types and stack memory

Basic data types

We know that there are seven basic data types of JS:

  • string
  • number
  • boolean
  • null
  • undefined
  • symbol
  • bigInt

Basic data type variables are held in stack memory because they take up small space, are fixed in size, are accessed by value and are frequently used data.

Next, let’s use an example to illustrate how basic data types are stored in stack memory:

let name = "White";
let age = 20;
Copy the code

In the above code, we define two variables:

  • The name forstringtype
  • The age ofnumbertype

Let’s draw a picture of how it’s stored in stack memory:

Note ⚠️ : The basic datatype variables in the closure are stored in heap memory. When a function returns a reference to an inner function after the pop-up call stack, the function’s variables are moved to the heap, so that the inner function still has access to the variables of the upper-level function.

Reference data type

All but the basic data types mentioned in the previous section are reference data types, such as Array, Function, Object, and so on.

Reference data types are stored in the heap memory. Reference data types occupy large space and have variable size. If stored on the stack, the running performance of the program will be affected.

The reference data type stores a pointer on the stack to the starting address of the entity in the heap memory space.

When the interpreter looks for a reference value, it retrieves its address in the stack, and when it retrieves the address, it retrieves the entity from the heap.

Let’s take an example to describe the above statement:

// Basic data type - stack memory
let name = "White";
// Basic data type - stack memory
let age = 20;
// Basic data type - stack memory
let info = null;
// The object pointer is stored in stack memory, and the object to which the pointer points is stored in heap memory
let msgObj = {msg: "Test".id: 5};
// The pointer to the array is stored in stack memory, and the pointer to the array is stored in heap memory
let ages = [19.22.57]
Copy the code

In the above code:

  • We created two variablesmsgObj,ages, their values are reference types (object, array)
  • Heap memory space is usedBinary heapAs a data structure,msgObjwithagesIs stored in the heap memory space
  • When the storage is complete, the heap memory space returns a reference address (pointer) to the two values
  • After getting the reference address, the reference address is stored in the stack memory space corresponding to its variable name
  • Finding variablesmsgObjwithagesGets its reference address from the stack memory space
  • After the reference address is obtained, the corresponding value is found in the binary heap of the heap memory space through the reference address.

Let’s draw a picture to illustrate the above words, as follows:

Objects in the heap memory space represent references to other objects stored in the space.

Let’s understand the difference between heap memory space and heap memory:

Heap memory space: equivalent to a container that uses binary heap as its data structure.

Heap memory: Refers to the specific value of a reference type.

Heap memory exists in the heap memory space.

Variable replication

Next, let’s look at variable replication from a memory perspective.

Replication of base data types

Let’s take a look at the basic type of copying as an example. The code looks like this:

let name = "The Amazing Programmer.";
let alias = name;
alias = "White";
Copy the code

In the above code:

  • name,aliasAre basic types, and their values are stored in stack memory.
  • They have their own stack space
  • Therefore, modifyaliasThe value of thenameIs not affected

Let’s draw a picture to illustrate it:

Replication of reference data types

Next, let’s look at copying a reference type with an example like this:

let book = {title:"Book".id: 12}
let info = book;
info.title = "Storybook";
console.log(book.title); / / story books
Copy the code

In the above code:

  • info,bookBoth are reference types, and their references are stored in stack memory and their values are stored in heap memory
  • Their values point to the same block of heap memory, and a copy of the same reference is made in stack memory

Let’s draw a picture to illustrate it:

Deep copy and shallow copy

Through the learning of the above chapters, we know that when the reference data type is copied, the value of one data will be changed, and the value of the other data will also be changed. This copying mode is called shallow copy.

In real development, we want reference types copied to new variables to be independent of each other and not affect the other because of changes in one. This type of copying is called deep copying.

Deep copy refers to creating a new space in the heap and copying the data from the original object into the new address space. Generally speaking, there are two methods:

  • The only problem with this method is that it can only convert common data, function, undefined, etc
  • Write loop traversal manually

Let’s look at the first method, which looks like this:

const data = { name: "White" };
const obj = JSON.parse(JSON.stringify(data));
obj.age = 20;
console.log("data = ", data);
console.log("obj = ", obj);

Copy the code

The running results are as follows:

Finally, let’s look at the second method, which looks like this:

const data = [{ name: "White" }];
let obj = data.map(item= > item);
obj.push({ name: "The Amazing Programmer." });
console.log("data = ", data);
console.log("obj = ", obj);
Copy the code

The running results are as follows:

The code address

This article is “JS principle learning” series of the fourth article, this series of complete route please move: JS principle learning (1) “learning route planning

For all the sample code in this series, go to jS-learning

Write in the last

At this point, the article is shared.

I’m an amazing programmer, a front-end developer.

If you are interested in me, please visit my personal website for further information.

  • If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
  • This article was first published in nuggets. Reprint is prohibited without permission 💌