Introduction to the

We use javascript on the Web. We use NodeJS on the server side. The first impression of JS is that it is simple, but not everyone has a systematic understanding of the built-in objects and data structures in JS.

Today, let’s take a look.

The base type

Js is a weakly typed dynamic language. Although it is weakly typed, JS itself defines many types of data.

There are seven basic types in js: undefined, Boolean, Number, String, BigInt, Symbol, and NULL.

undefined

Undefined is automatically assigned to the variable just declared. Here’s an example:

var x; //create a variable but assign it no value

console.log("x's value is", x) //logs "x's value is undefined"
Copy the code

Boolean and Boolean objects

Boolean is either true or false.

In addition to the Boolean values of the base type, there is a Boolean object that encapsulates the Boolean values.

If new Boolean is used to construct a Boolean object, Boolean starts with false in the following examples:

var bNoParam = new Boolean();
var bZero = new Boolean(0);
var bNull = new Boolean(null);
var bEmptyString = new Boolean('');
var bfalse = new Boolean(false);
Copy the code

The Number and BigInt

Number and BigInt are two numeric types in JS, where Number represents a double precision 64-bit binary format that ranges from -(253 − 1) to 253 − 1.

In addition, Number has three values: +Infinity, -infinity, and NaN.

The first two are positive and negative maxima. NaN stands for not-a-number.

We can use isNaN to determine if it is a Number:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

console.log(sanitise('1'));
// expected output: "1"

console.log(sanitise('NotANumber'));
// expected output: NaN

Copy the code

BigInt represents an integer of arbitrary precision. You can use BigInt to perform operations that exceed the precision of Number.

We can indicate BigInt by adding n to the integer.

> const x = 2n ** 53n;
9007199254740992n
> const y = x + 1n; 
9007199254740993n
Copy the code

Note that, like Boolean, Number and BitInt have wrapper object types.

Look at the wrapper for Number:

Number('123')  // returns the number 123
Number('123') === 123  // true

Number("unicorn")  // NaN
Number(undefined)  // NaN
Copy the code

Look at the Wrapper type of BitInt:

Const theBiggestInt = 9007199254740991n const alsoHuge = BigInt(9007199254740991) // ↪ 9007199254740991n const HugeString = BigInt("9007199254740991") // ↪ 9007199254740991n const hugeHex = BigInt(" 0x1FFFFFFfffff ") // ↪ 9007199254740991 n const hugeBin = BigInt / / ↪ (b11111111111111111111111111111111111111111111111111111 "0") 9007199254740991nCopy the code

The following Boolean objects all start with true:

var btrue = new Boolean(true);
var btrueString = new Boolean('true');
var bfalseString = new Boolean('false');
var bSuLin = new Boolean('Su Lin');
var bArrayProto = new Boolean([]);
var bObjProto = new Boolean({});
Copy the code

Note that we do not use Boolean objects for if conditions. Any Boolean object, even a Boolean object whose initial value is false, is true:

var x = new Boolean(false);
if (x) {
  // this code is executed
}

var x = false;
if (x) {
  // this code is not executed
}
Copy the code

If you must use the if condition, you can use the Boolean function or!! As follows:

var x = Boolean(expression); // use this... var x = !! (expression); / /... or this var x = new Boolean(expression); // don't use this!Copy the code

String

Js String is immutable, and the base type of String has a Corresponding String Wrapper object.

The base String type is the same as the String function that does not use new:

const string1 = "A string primitive";
const string2 = String('A string primitive');
Copy the code

The above two strings are the same. But if we use new to construct a String, the two are different:

let s_prim = 'foo'
let s_obj = new String(s_prim)

console.log(typeof s_prim) // Logs "string"
console.log(typeof s_obj)  // Logs "object"

let s1 = '2 + 2'              // creates a string primitive
let s2 = new String('2 + 2')  // creates a String object
console.log(eval(s1))         // returns the number 4
console.log(eval(s2))         // returns the string "2 + 2"
Copy the code

We can get the String base type from the valueOf() method on a String.

Symbol

Symbol is a unique immutable base type commonly used in object keys.

// Here are two symbols with the same description:
let Sym1 = Symbol("Sym")
let Sym2 = Symbol("Sym")

console.log(Sym1 === Sym2) // returns "false"
Copy the code

Symbol does not support the new operation:

let sym = new Symbol()  // TypeError
Copy the code

If you really want to create a Symbol Object, you can use Object() :

let sym = Symbol('foo')
typeof sym      // "symbol" 
let symObj = Object(sym)
typeof symObj   // "object"
Copy the code

null

Null refers to an invalid Object or address.

Although null can be considered primitive, null is actually an Object and all objects come from NULL:

typeof null === 'object' // true
Copy the code

Object

Object is a data type in JS. Almost all objects inherit from Object, which stores key-value data. We can create Object by using Ojbect() method or New Object() or Object literal.

let o = {}
let o = {a: 'foo', b: 42, c: {}}

let a = 'foo', b = 42, c = {}
let o = {a: a, b: b, c: c}
Copy the code

Note that using Object() or new Object() has the same effect; both get an Object. \

After ES2015, we can also use dynamic object properties:

let param = 'size'
let config = {
  [param]: 12,
  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
}

console.log(config) // {size: 12, mobileSize: 4}
Copy the code

Function

Function is also an Object, and all functions in JS are Function objects.

(function(){}).constructor === Function
Copy the code

So what’s the difference between a Function created by a Function constructor and a Function definition?

A Function created with new Function is global in scope. Let’s look at an example:

var x = 10; function createFunction1() { var x = 20; return new Function('return x; '); // this |x| refers global |x| } function createFunction2() { var x = 20; function f() { return x; // this |x| refers local |x| above } return f; } var f1 = createFunction1(); console.log(f1()); // 10 var f2 = createFunction2(); console.log(f2()); / / 20Copy the code

Date

Date is an Object used to manipulate time in JS. Let’s look at a common example of Date:

let today = new Date() let birthday = new Date('December 17, 1995 03:24:00') let birthday = new Date('1995-12-17T03:24:00') let birthday = new Date(1995, 11, 17) // the month is 0-indexed let birthday = new Date(1995, 11, 17, 3, 24, 0) let birthday = new Date(628021800000) // passing epoch timestamp let [month, date, year] = ( new Date() ).toLocaleDateString().split("/") let [hour, minute, Second] = (new Date().tolocaletimestring ().slice(0,7).split(":")Copy the code

Array

There are many different types of arrays built into JS. The most common ones are Array literals and Array objects.

Let’s see how to create an Array:

let fruits = ['Apple', 'Banana'];

console.log(fruits.length); // 2
console.log(fruits[0]);     // "Apple"

let fruits = new Array('Apple', 'Banana');

console.log(fruits.length); // 2
console.log(fruits[0]);     // "Apple"
Copy the code

Traverse the Array:

let fruits = ['Apple', 'Banana']
fruits.forEach(function(item, index, array) {
  console.log(item, index)
})
// Apple 0
// Banana 1
Copy the code

Add Item to Array:

let newLength = fruits.push('Orange')
// ["Apple", "Banana", "Orange"]
Copy the code

Delete item from last:

let last = fruits.pop() // remove Orange (from the end)
// ["Apple", "Banana"]
Copy the code

Delete item from previous:

let first = fruits.shift() // remove Apple from the front
// ["Banana"]
Copy the code

Add item from the front:

let newLength = fruits.unshift('Strawberry') // add to the front
// ["Strawberry", "Banana"]
Copy the code

Delete an item from index:

let removedItem = fruits.splice(pos, 1) // this is how to remove an item

// ["Strawberry", "Mango"]
Copy the code

Delete multiple items:

let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']
console.log(vegetables)
// ["Cabbage", "Turnip", "Radish", "Carrot"]

let pos = 1
let n = 2

let removedItems = vegetables.splice(pos, n)
// this is how to remove items, n defines the number of items to be removed,
// starting at the index position specified by pos and progressing toward the end of array.

console.log(vegetables)
// ["Cabbage", "Carrot"] (the original array is changed)

console.log(removedItems)
// ["Turnip", "Radish"]
Copy the code

Copy an array:

let shallowCopy = fruits.slice() // this is how to make a copy
// ["Strawberry", "Mango"]
Copy the code

In addition to arrays, JS also has a specific type of Array built in:

  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array
  • BigInt64Array
  • BigUint64Array

Only certain types of values can be stored in these specific types of arrays.

Keyed collections

In addition to arrays, there are also collections of key-values in JS, such as Map, Set, WeakMap and WeakSet.

For a Map, we can use set, get, HAS, delete, etc to manipulate a Map:

let contacts = new Map()
contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})
contacts.has('Jessie') // true
contacts.get('Hilary') // undefined
contacts.set('Hilary', {phone: "617-555-4321", address: "321 S 2nd St"})
contacts.get('Jessie') // {phone: "213-555-1234", address: "123 N 1st Ave"}
contacts.delete('Raymond') // false
contacts.delete('Jessie') // true
console.log(contacts.size) // 1
Copy the code

Through the Map:

let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')

for (let [key, value] of myMap) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

for (let key of myMap.keys()) {
  console.log(key)
}
// 0
// 1

for (let value of myMap.values()) {
  console.log(value)
}
// zero
// one

for (let [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
Copy the code

Use forEach to traverse the map:

myMap.forEach(function(value, key) {
  console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one
Copy the code

A Set stores a unique object.

Let’s look at the Set operation:

let mySet = new Set()

mySet.add(1)           // Set [ 1 ]
mySet.add(5)           // Set [ 1, 5 ]

mySet.has(1)              // true
mySet.delete(1)    // removes 1 from the set
Copy the code

Set traversal:

// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} 
for (let item of mySet) console.log(item)
Copy the code

The difference between WeakMap,WeakSet, Map and Set is that the key of WeakMap can only be an Object Object, not the basic type.

Why does WeakMap exist?

For a Map in JS, you usually need to maintain two arrays, the first containing the key and the second containing the value. Each time you add and remove an item, you need to operate on both arrays.

This implementation has two disadvantages. The first disadvantage is that each search needs to traverse the array of keys, and then find the corresponding index, and then use the index to find the value from the second array.

The second disadvantage is that the key and value are strongly bound, and even if the key is no longer in use, it will not be garbage collected.

Therefore, the concept of WeakMap is introduced. In WeakMap, there is no such strong binding relationship between key and value. If key is no longer used, it can be recovered by garbage collector.

WeakMap does not support key traversal because the reference relationship is weak. If you want to traversal key, please use Map.