Lesson 01-Data Types & Operators & Standard Libraries

Data Types

JS basic data types:

  • number:
  • string:
  • boolean:
  • undefined:
  • null:
  • object(object/array/function):
  • symbol:

Operators

Arithmetic operators:

These operators are used to perform basic mathematical calculations:

  • +: Addition operator, used for adding numbers or concatenating strings.
  • -: Subtraction operator, used to subtract values.
  • *: Multiplication operator, used to multiply numbers.
  • /: Division operator, used to divide numbers.
  • %: Modulo (remainder) operator, returns the remainder after dividing two numbers.
  • **: Exponential operator, calculates a number raised to the power of another number.

Equality operator

Used to compare two values ​​for equality or strict equality:

  • ==: Equality operator, compares the equality of the values ​​on both sides, and performs type conversion before comparison.
  • ===: The strict equality operator compares the equality and type of the values ​​on both sides and returns true only when the values ​​and types are the same.

Comparison operators:

Used to compare the size of numbers or strings:

  • <: Less than operator, checks if the value on the left is less than the value on the right.
  • > : Greater than operator, checks if the value on the left is greater than the value on the right.
  • <=: Less than or equal to operator, checks whether the value on the left is less than or equal to the value on the right.
  • > =: Greater than or equal to operator, checks whether the value on the left is greater than or equal to the value on the right.

Logical operators

Used to perform logical judgments and combine Boolean expressions:

  • && (logical AND): If both operands are true, the result is true.
  • || (logical OR): The result is true if at least one of the operands is true.
  • ! (logical NOT): negates the operand. If the operand is true, the result is false, and vice versa.

Assignment Operators

Used to assign values ​​or compound assignments to variables:

  • =: Basic assignment operator, assigns the value on the right to the variable on the left.
  • +=, -=, *=, /=, %=: Compound assignment operators that assign the corresponding arithmetic operation results on both sides to the variables on the left.
  • **=: Exponential assignment operator, which assigns the exponential operation results on both sides to the variable on the left.
  • <<=, >>=, >>>=: Shift assignment operators that assign the results of the shift operations on both sides to the variables on the left.
  • &=, |=, ^=: Bitwise assignment operators that assign the results of the bitwise AND, bitwise OR, and bitwise XOR operations on both sides to the variable on the left.

Bitwise operators:

For bit-level operations on binary representations of integers:

  • &(Bitwise AND): Performs an AND operation on the corresponding binary bits of the two operands.
  • |(Bitwise OR): Performs an OR operation on corresponding binary bits of the two operands.
  • ^(Bitwise XOR): Performs XOR operation on corresponding binary bits of two operands.
  • ~(Bitwise NOT): Inverts each bit of the operand.
  • <<(Left Shift): Shift the binary representation of the operand to the left by the specified number of bits, filling the vacant bits with zeros.
  • >>(Right shift, signed): Shift the binary representation of the operand to the right by the specified number of bits. For positive numbers, the high bits are filled with zeros; for negative numbers, whether one or zero is filled depends on the original sign bit.
  • >>>(Unsigned right shift): Shift the binary representation of the operand to the right by the specified number of bits, regardless of whether it is positive or negative, and fill the high bits with zeros.

String operators

In fact, there are no dedicated string operators in JavaScript, but you can use the plus sign (+) to concatenate strings.

Conditional (ternary) operator

A concise conditional expression:

condition ? exprIfTrue : exprIfFalse

If condition is truthy, it returns the value of exprIfTrue, otherwise it returns the value of exprIfFalse.

Comma operator

Used to perform multiple operations in one statement and return the result of the last operation:

var x = (a = 1, b = 2, c = 3);
// Here the value of x is 3, and a, b, and c are also assigned values ​​of 1, 2, and 3 respectively

Nullish coalescing operator (??)

It is used to check whether the left expression is null or undefined. If so, it returns the right expression, otherwise it returns the left expression:

let value = null;
let fallback = 'default';
console.log(value ?? fallback); // Output "default"

Nullish coalescing operator (?.)

Used to safely access nested object properties or call chained methods. If a reference in the middle path is null or undefined, the entire expression returns undefined instead of throwing an error:

let obj = { nested: { prop: 'value' } };
console.log(obj.nested?.prop); // Output "value"
console.log(obj.missing?.prop); // Output undefined, no error

Order of operations:

Operators in JavaScript follow specific precedence rules that determine the order in which the parts of an expression are evaluated. From highest to lowest, the precedence of operators is roughly as follows:

  1. Parentheses (): The expression inside the parentheses is evaluated first.
  2. Postfix increment/decrement operator,– (such as x,and-)
  3. Prefix increment/decrement operator ++, – (e.g. ++x, –y)
  4. Unary operators (+, -, !, ~, void, delete, typeof, ++, –)
  5. Multiplication, division, modulo *, /, %
  6. Addition, subtraction +, –
  7. Bitwise left shift, right shift, unsigned right shift <<, >>, >>>
  8. Less than, Greater than, Less than or equal to, Greater than or equal to <, >, <=, >=
  9. Equivalence, Congruence==!====!==
  10. Logical AND &&
  11. Logical OR ||
  12. Comma,: When multiple expressions are separated by commas, each expression is calculated from left to right, and the result of the entire expression is the value of the last expression.

When there are operators of the same priority in an expression, they are associative from left to right. If you need to change the default order of operations, you can use parentheses to explicitly specify the order of calculation.

Data type conversion:

Implicit type conversion (automatic conversion):

In expression calculation : When different types of data are used for arithmetic operations, comparison operations, logical operations, etc., JavaScript will automatically perform type conversion to ensure the feasibility of the operation. For example:

  • stringnumber→ string(string concatenation)
  • numberboolean→ number(converts a Boolean value to a number 0 or 1)
  • nullor undefinedand numerical operation → treat it as 0 for operation
  • Object and numerical operations → First call the object’s valueOf()method, if it returns a primitive type, perform the operation, otherwise call toString()the method and try to convert it to a numerical value

As function parameters : Some functions (such as alert(), parseInt(), etc.) accept parameters of specific types and implicitly convert the actual parameter type passed in.

Explicit type conversion (casting):

Use the transformation function:

  • Number(value): Convert the value to number type. If the value cannot be converted, NaN is returned.
  • String(value): Convert the value to string type.
  • Boolean(value): Convert the value to boolean type and determine the result as trueor according to the conversion rules false.

Use the cast operator:

  • value.toString(): Object method, converts an object to a string.
  • value.valueOf(): Object method that returns the primitive value representation of an object.
  • +valueOr value * 1: Converts a value to a numeric value, suitable for strings, Boolean values, etc.
  • !!value: Perform two logical NOT operations to convert the value to Boolean type.

Standard library objects

Object:

var obj = Object()
obj instanceof Object // true
Object.keys(): // Traverse the properties of an object
Object.getOwnPropertyNames(): // Traverse the properties of an object
Object.getOwnPropertyDescriptor(): // Get the description object of a property.
Object.defineProperty(): // Define a property by describing the object.
Object.defineProperties(): // Define multiple properties by describing the object.
Object.preventExtensions(): // Prevent object extension.
Object.isExtensible(): // Determine whether the object is extensible.
Object.seal(): // Prohibit object configuration.
Object.isSealed(): // Determine whether an object is configurable.
Object.freeze(): // Freeze an object.
Object.isFrozen(): // Determine whether an object is frozen.
Object.create(): // This method can specify the prototype object and properties and return a new object.
Object.getPrototypeOf(): // Get the Prototype object of the object
Object.prototype.valueOf(): // Return the value corresponding to the current object.
Object.prototype.toString(): // Return the string form corresponding to the current object.
Object.prototype.toLocaleString(): // Return the local string form corresponding to the current object.
Object.prototype.hasOwnProperty(): // Determine whether a property is a property of the current object itself or a property inherited from the prototype object.
Object.prototype.isPrototypeOf(): // Determine whether the current object is the prototype of another object.
Object.prototype.propertyIsEnumerable(): // Determine whether a property is enumerable.

Attributes describing the object:

{
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false,
  get: undefined,
  set: undefined
}

// Accessor
var obj = Object.defineProperty({}, 'p', {
  get: function () {
    return 'getter';
  },
  set: function (value) {
    console.log('setter: ' + value);
  }
});

Array object:

  • Array.isArray(): Determine whether it is an array type;
  • valueOf(): Evaluate the object, valueOfthe method returns the array itself;
  • toString(): Evaluate the object, toStringthe method returns the string form of the array;
  • push(): The push method is used to add one or more elements to the end of the array and return the length of the array after adding the new elements. This method will change the original array.
  • pop(): The pop method is used to delete the last element of an array and return the element. This method will change the original array;
  • shift(): The shift() method is used to delete the first element of an array and return the element. This method will change the original array;
  • unshift(): Add an element to the first position of the array and return the length of the array after adding the new element. This method will change the original array;
  • join(): Use the specified parameter as the delimiter to connect all array members into a string and return it. If no parameter is provided, commas are used as separators by default;
  • concat(): Used to merge multiple arrays. It adds the members of the new array to the end of the members of the original array, and then returns a new array, leaving the original array unchanged;
  • reverse(): Used to reverse the arrangement of array elements and return the changed array. Note that this method will change the original array;
  • slice(): Used to extract a part of the target array and return a new array, while the original array remains unchanged;
  • splice(): Delete some members of the original array and add new array members at the deleted position. The return value is the deleted element. This method will change the original array.
  • sort(): Sort the array members. The default is to sort in lexicographical order. After sorting, the original array will be changed;
  • map(): Pass all members of the array into the parameter function in sequence, and then return the results of each execution as a new array;
  • forEach(): Array traversal;
  • filter(): Used to filter array members. The members that meet the conditions form a new array and return;
  • some(): Array traversal, as long as the return value of one member is true, the return value of the entire some method is true, otherwise it returns false;
  • every(): Array traversal, the return value of all members is true, the entire every method returns true, otherwise it returns false;
  • reduce(): The method processes each member of the array in turn and finally accumulates to a value. Reduce is processed from left to right (from the first member to the last member);
  • reduceRight(): The method processes each member of the array in turn and finally accumulates to a value, while reduceRight is from right to left (from the last member to the first member);
  • indexOf(): Returns the position of the first occurrence of a given element in the array, or -1 if it does not appear.
  • lastIndexOf(): Returns the position of the last occurrence of a given element in the array, or -1 if it does not appear.
  • Chain use: Many of the above array methods return arrays, so they can be chained.

Package Object:

The three primitive types of values—numbers, strings, and Boolean values—are also automatically converted to objects under certain conditions, that is, “wrapper objects” of the primitive types;

var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);

Wrapper object instance methods: valueOf() and toString() The valueOf() method returns the value of the original type corresponding to the wrapped object instance;

new Number(123).valueOf()  // 123
new String('abc').valueOf() // "abc"
new Boolean(true).valueOf() // true

The toString() method returns the corresponding string form;

new Number(123).toString() // "123"
new String('abc').toString() // "abc"
new Boolean(true).toString() // "true"

The value of the primitive type is automatically called as the wrapped object, that is, the properties and methods of the wrapped object are called. At this time, the JavaScript engine will automatically convert the value of the primitive type into a wrapped object instance and destroy the instance immediately after use.

Boolean object:

The Boolean object is one of the three wrapper objects in JavaScript. As a constructor, it is mainly used to generate wrapper object instances of Boolean values.

var b = new Boolean(true);
typeof b // "object"
b.valueOf() // true

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean('') // false
Boolean(NaN) // false
Boolean(1) // true
Boolean('false') // true
Boolean([]) // true
Boolean({}) // true
Boolean(function () {}) // true
Boolean(/foo/) // true

!!undefined // false
!!null // false
!!0 // false
!!'' // false
!!NaN // false

Number object:

var n = new Number(1);
typeof n // "object"
Number(true) // 1

The Number object has the following static properties:

  • Number.POSITIVE_INFINITY: Positive infinity, pointing to Infinity.
  • Number.NEGATIVE_INFINITY: Negative infinity, pointing to -Infinity.
  • Number.NaN: Represents non-numeric value, pointing to NaN.
  • Number.MIN_VALUE: Represents the smallest positive number (that is, the positive number closest to 0, which is 5e-324 in the 64-bit floating point system). Correspondingly, the negative number closest to 0 is -Number.MIN_VALUE.
  • Number.MAX_SAFE_INTEGER: represents the largest integer that can be represented exactly, which is 9007199254740991.
  • Number.MIN_SAFE_INTEGER: represents the smallest integer that can be represented exactly, that is, -9007199254740991.

Instance methods:

  • Number.prototype.toString(): Convert a value to a string;
  • Number.prototype.toFixed(): First convert a number into a decimal with the specified number of digits, and then return the string corresponding to the decimal;
  • Number.prototype.toExponential(): Convert a number to scientific notation;
  • Number.prototype.toPrecision(): Convert a number to a specified number of valid digits;
  • Number.prototype.toLocaleString(): Accepts a region code as a parameter and returns a string representing the local writing form of the current number in that region;
  • Custom method: Number.prototype.add = function (x) {return this + x};

String object:

The String object is one of the three wrapper objects provided by JavaScript natively, used to generate string objects

Static methods:

  • String.fromCharCode(): The parameters of this method are one or more numerical values ​​representing Unicode code points, and the return value is a string composed of these code points;

Instance attributes:

  • String.prototype.length: The length property of a string instance returns the length of the string;

Instance methods:

  • String.prototype.charAt(): Returns the character at the specified position, the parameter is the position numbered starting from 0;
  • String.prototype.charCodeAt(): Returns the Unicode code point (in decimal) at the specified position in the string, which is equivalent to the inverse operation of String.fromCharCode();
  • String.prototype.concat(): Used to concatenate two strings and return a new string without changing the original string;
  • String.prototype.slice(): It is used to extract a substring from the original string and return it without changing the original string. Its first parameter is the starting position of the substring, and the second parameter is the ending position of the substring (not including this position);
  • String.prototype.substring(): It is used to extract a substring from the original string and return it without changing the original string. It is very similar to the slice method. Its first parameter indicates the starting position of the substring, and the second position indicates the ending position (the returned result does not include this position);
  • String.prototype.substr(): Used to extract a substring from the original string and return it without changing the original string. It has the same function as the slice and substring methods;
  • String.prototype.indexOf(): This method is used to determine the first occurrence of a string in another string, and the return result is the position where the match starts. If -1 is returned, it means no match;
  • String.prototype.lastIndexOf(): The indexOf method is the same, the main difference is that lastIndexOf starts matching from the end, while indexOf starts matching from the beginning;
  • String.prototype.trim(): Used to remove spaces at both ends of a string and return a new string without changing the original string;
  • String.prototype.toLowerCase(): Convert a string to lowercase;
  • String.prototype.toUpperCase(): Convert a string to uppercase;
  • String.prototype.match(): Used to determine whether the original string matches a substring, and returns an array whose members are the first matching string. If no match is found, it returns null;
  • String.prototype.search(): Basically the same as match, but the return value is the first position of the match. If no match is found, -1 is returned;
  • String.prototype.replace(): Used to replace the matched substring, generally only the first match is replaced (unless a regular expression with the g modifier is used);
  • String.prototype.split(): Split the string according to the given rules and return an array of the split substrings;
  • String.prototype.localeCompare(): Used to compare two strings. It returns an integer. If it is less than 0, it means that the first string is less than the second string; if it is equal to 0, it means that the two are equal; if it is greater than 0, it means that the first string is greater than the second string;

Math object:

Static properties:

  • Math.E: constant e.
  • Math.LN2: The natural logarithm of 2.
  • Math.LN10: The natural logarithm of 10.
  • Math.LOG2E: Logarithm of e to base 2.
  • Math.LOG10E: Logarithm of e to base 10.
  • Math.PI: constant π.
  • Math.SQRT1_2: square root of 0.5.
  • Math.SQRT2: square root of 2.

Static methods:

  • Math.abs(): Absolute value
  • Math.ceil(): Round up
  • Math.floor(): Round down
  • Math.max(): Maximum value
  • Math.min(): Minimum
  • Math.pow(): Power operation
  • Math.sqrt(): Square root
  • Math.log(): Natural logarithm
  • Math.exp(): exponent of e
  • Math.round():rounding
  • Math.random(): Random number

Trigonometric methods:

  • Math.sin(): Returns the sine of the parameter (the parameter is a radian value)
  • Math.cos(): Returns the cosine of the argument (the argument is a radian value)
  • Math.tan(): Returns the tangent of the argument (the argument is a radian value)
  • Math.asin(): Returns the arc sine of the parameter (the return value is in radians)
  • Math.acos(): Returns the arc cosine of the parameter (the return value is in radians)
  • Math.atan(): Returns the arc tangent of the parameter (the return value is in radians)

Date object:

Usage of ordinary functions:

Date();
Date(2000, 1, 1)

Usage of the constructor:

var today = new Date();
// The parameter is the number of milliseconds from zero o'clock
new Date(1378218728000)
// Tue Sep 03 2013 22:32:08 GMT+0800 (CST)
new Date(-1378218728000)
// Fri Apr 30 1926 17:27:52 GMT+0800 (CST)
// The parameter is a date string
new Date('January 6, 2013');
// Sun Jan 06 2013 00:00:00 GMT+0800 (CST)
// The parameter is multiple integers,
// representing year, month, day, hour, minute, second, millisecond
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date('2013-2-15')
new Date('2013/2/15')
new Date('02/15/2013')
new Date('2013-FEB-15')
new Date('FEB, 15, 2013')
new Date('FEB 15, 2013')
new Date('February, 15, 2013')
new Date('February 15, 2013')
new Date('15 Feb 2013')
new Date('15, February, 2013')
newDate(2013, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)

Date operations:

var d1 = new Date(2000, 2, 1);
var d2 = new Date(2000, 3, 1);
d2 - d1
// 2678400000
d2 + d1
// "Sat Apr 01 2000 00:00:00 GMT+0800 (CST)Wed Mar 01 2000 00:00:00 GMT+0800 (CST)"

Static methods:

  • Date.now(): Returns the number of milliseconds from the current time (00:00:00 UTC, January 1, 1970), which is equivalent to the Unix timestamp multiplied by 1000;
  • Date.parse(): Used to parse the date string and return the number of milliseconds from the time zero (00:00:00 on January 1, 1970).
  • Date.UTC(): The method accepts variables such as year, month, and day as parameters and returns the number of milliseconds from the time zero (January 1, 1970 00:00:00 UTC);

Instance methods:

  • Date.prototype.valueOf(): Returns the number of milliseconds corresponding to the instance object from the time zero (00:00:00 UTC on January 1, 1970). This method is equivalent to the getTime method.
  • Date.prototype.toString(): Returns a complete date string.
  • Date.prototype.toUTCString(): Returns the corresponding UTC time, which is 8 hours later than Beijing time.
  • Date.prototype.toISOString(): Returns the ISO8601 format of the corresponding time.
  • Date.prototype.toJSON(): Returns an ISO date string that conforms to the JSON format, which is exactly the same as the return result of the toISOString method.
  • Date.prototype.toDateString(): The method returns a date string (excluding hours, minutes and seconds).
  • Date.prototype.toTimeString(): The method returns a time string (excluding year, month, and day).
  • Date.prototype.toLocaleString(): The complete local time.
  • Date.prototype.toLocaleDateString(): Local date (without hours, minutes, and seconds).
  • Date.prototype.toLocaleTimeString(): Local time (excluding year, month, and day).
  • getTime(): Returns the number of milliseconds from January 1, 1970 00:00:00, which is equivalent to the valueOf method.
  • getDate(): Returns the day of each month (starting from 1) corresponding to the instance object.
  • getDay(): Returns the day of the week, with Sunday being 0, Monday being 1, and so on.
  • getFullYear(): Returns the four-digit year.
  • getMonth(): Returns the month (0 for January, 11 for December).
  • getHours(): Returns the hour (0-23).
  • getMilliseconds(): Returns milliseconds (0-999).
  • getMinutes(): Returns the minute (0-59).
  • getSeconds(): Returns the second (0-59).
  • getTimezoneOffset(): Returns the time zone difference between the current time and UTC, expressed in minutes. The returned result takes daylight saving time into account.
  • setDate(date): Set the day of each month (1-31) corresponding to the instance object and return the millisecond timestamp after the change.
  • setFullYear(year [, month, date]): Set the four-digit year.
  • setHours(hour [, min, sec, ms]): Set the hour (0-23).
  • setMilliseconds(): Set milliseconds (0-999).
  • setMinutes(min [, sec, ms]): Set the minute (0-59).
  • setMonth(month [, date]): Set the month (0-11).
  • setSeconds(sec [, ms]): Set seconds (0-59).
  • setTime(milliseconds): Set millisecond timestamp.

RegExp object:

There are two ways to create a new regular expression:

var regex = /xyz/; // Method 1
var regex = new RegExp('xyz'); // Method 2

Instance attributes:

  • RegExp.prototype.ignoreCase: Returns a Boolean value indicating whether the i modifier is set.
  • RegExp.prototype.global: Returns a Boolean value indicating whether the g modifier is set.
  • RegExp.prototype.multiline: Returns a Boolean value indicating whether the m modifier is set.
  • RegExp.prototype.flags: Returns a string containing all the modifiers that have been set, sorted alphabetically.
  • RegExp.prototype.lastIndex: Returns an integer indicating the next starting position for the search. This property is readable and writable, but is only meaningful when performing a continuous search. Please see the following text for details.
  • RegExp.prototype.source: Returns the string form of the regular expression (without backslashes). This property is read-only.

Instance methods:

  • RegExp.prototype.test(): The test method of the Regular Expression instance object returns a Boolean value indicating whether the current pattern can match the parameter string.
/cat/.test('cats and dogs') // true
var r = /x/g;
var s = '_x_x';
r.lastIndex // 0
r.test(s) // true
  • RegExp.prototype.exec(): The exec() method of the regular expression instance object is used to return the matching result. If a match is found, an array is returned, the members of which are the substrings that matched successfully, otherwise null is returned.
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
r1.exec(s) // ["x"]
r2.exec(s) // null

String instance methods:

  • String.prototype.match(RegExp): Returns an array whose members are all matching substrings.
  • String.prototype.search(RegExp): Search according to the given regular expression and return an integer indicating the position where the match starts.
  • String.prototype.replace(RegExp): Replace according to the given regular expression and return the replaced string.
  • String.prototype.split(RegExp): Split the string according to the given rules and return an array containing the split members.

Matching rules:

/dog/.test('old dog') // true

// test must appear at the start
/^test/.test('test123') // true
// test must appear at the end
/test$/.test('new test') // true
// only test from the start to the end
/^test$/.test('test') // true
/^test$/.test('test test') // false
/11|22/.test('911') // true

// match one of fred, barney, betty
/fred|barney|betty/
/a( |\t)b/.test('a\tb') // true

/1+1/.test('1+1')
// false
/1\+1/.test('1+1')
// true

(new RegExp('1\+1')).test('1+1')
// false
(new RegExp('1\\+1')).test('1+1')
// true

/[abc]/.test('hello world') // false
/[abc]/.test('apple') // true

/[^abc]/.test('bbc news') // true
/[^abc]/.test('bbc') // false

var s = 'Please yes\nmake my day!';
s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ 'yes\nmake my day']

/a-z/.test('b') // false
/[a-z]/.test('b') // true

var str = "\u0130\u0131\u0132";
/[\u0128-\uFFFF]/.test(str)
// true

/[A-z]/.test('\\') // true

// Normal match
var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
url.exec('http://google.com/');
// ["http://google.com/", "http", "google.com", "/"]
// Non-capture group match
var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
url.exec('http://google.com/');
// ["http://google.com/", "google.com", "/"]

JSON object:

The JSON object is a native object of JavaScript, used to process JSON format data. It has two static methods: JSON.stringify() and JSON.parse();

JSON.stringify()

// Parameter 1: Parameter object
// Parameter 2: Specify the attribute to be converted to a string. It can be a function to change the return value of JSON.stringify.
// Parameter 3: Increase the readability of the returned JSON string. If it is a number, it indicates the space added before each attribute;
JSON.stringify({ p1: 1, p2: 2 }, null, 2);
  • toJSON(): directly use the return value of this method as a parameter, and ignore other parameters of the original object

JSON.parse()

var o = JSON.parse('{"name": "Tom"}');
o.name // Tom

Garbage collection mechanism and internal algorithm

The garbage collection (GC) mechanism in JavaScript is mainly used to automatically manage memory allocation and release, reducing the burden on developers. The two main strategies used are Mark-and-Sweep and Reference Counting**. Modern JavaScript engines (such as V8) mainly use the mark-and-sweep algorithm, while reference counting may cause memory leaks in some cases (such as circular references), so it is gradually marginalized. The following introduces these two garbage collection mechanisms:

Mark-and-Sweep

Marking phase: When the memory space is insufficient or a certain time interval is reached, the garbage collector starts working. It first marks all objects reachable from the root object (such as the global object, the variable in the execution context stack), that is, it traverses all the references of the root object’s attributes, closures, callback functions, etc., and marks all objects that can be accessed through these reference chains as “active”.

Cleanup phase: Next, the garbage collector traverses all objects in the heap memory, considers objects that are not marked as “active” as garbage, and releases the memory space they occupy. These objects will no longer be accessed by the program, so they can be safely destroyed.

In order to improve performance, modern garbage collectors usually use techniques such as incremental marking and concurrent marking to spread the marking process into multiple cycles or execute it in parallel with the main thread of the program to reduce the impact on program execution.

Reference Counting

Reference counting tracks the number of times an object is referenced by maintaining a counter. Each time a new reference points to the object, the counter is incremented by 1; when the reference is removed or points to another object, the counter is decremented by 1. When the counter drops to 0, it means that the object has no references pointing to it, and the garbage collector can immediately reclaim the memory it occupies.

Circular reference problem: A major problem with the reference counting method is that it cannot handle circular references. For example, if two objects reference each other but are no longer accessed externally, their reference counts are both non-zero, causing the garbage collector to be unable to recycle them correctly:

const objA = { ref: null };
const objB = { ref: null };
objA.ref = objB; // objA references objB, objB's counter +1
objB.ref = objA; // objB references objA, objA's counter +1

// Now objA and objB reference each other, but are no longer referenced by other variables
// At this point, their reference counters are both 1 and will not be recycled by the garbage collector, causing memory leaks

Since modern JavaScript engines mainly use the mark-clearing algorithm, the above circular reference problem will not occur in most cases. However, in some old implementations or specific situations (such as using WeakRef, FinalizationRegistry and other APIs), the reference counting method may still be used.

Other garbage collection strategies

In addition to mark-sweep and reference counting, there are some other garbage collection strategies, such as copying, mark-compact, etc., which may be adopted or used in combination in some JavaScript engines.

  • Copy algorithm: Divide the memory into two blocks, and use only one of them at a time. When garbage collecting, copy the surviving objects to another memory area, and then clean up all the objects in the original area. This method is simple and efficient, but it will waste half of the memory space.
  • Mark compression: Similar to mark-sweep, but the memory is organized during the sweep phase, surviving objects are compactly arranged, memory fragmentation is eliminated, and memory utilization is improved.

Share your love