type

Up to now (ES2021),JS has a total of eight built-in data types, respectively

  • A null value (null)
  • Undefined (undefined)
  • Number (number)
  • Boolean (Boolean)
  • String (string)
  • Symbol (symbol)
  • Large integer (bigint)
  • Object (object)

Bigint is a basic type added in ES2020. It is used to solve the problem that JS has lost the accuracy of large numbers. The maximum accuracy of ordinary numbers without bigINT is Number. The minimum precision is number.min_safe_INTEGER, which is 9007199254740991(2^53-1) and -9007199254740991 (-(2^53-1)) respectively. Beyond this range, accuracy will be lost.

const a = -9007199254740991 - 100;
console.log(a); / / - 9007199254741092
console.log(a === a - 1); // true
Copy the code

Bigint is designed to solve this problem. To create a bigInt, there are two ways.

const first = 10000000000000000000000n // Add n to the number
const second = const c = BigInt('100000000000000000000000000')
/ / n here if you need to create more than 100000000000000000000000000 the number of maximum safe value need to string figures, otherwise will still be super precision, because the parameter itself ultra precision
Copy the code

For more details, check out this article juejin.cn/post/684490…

Type judgment

typeof

All values except null get the correct type

const bool = true;
const num = 1;
const str = "hello";
const sym = Symbol("demo");
const obj = {};
const bigint = 1000000000000000000000000n;

console.log(typeof obj); // object
console.log(typeof bigint); // bigint
console.log(typeof undefined); // undefined
console.log(typeof null); // object <- special
console.log(typeof sym); // symbol
console.log(typeof str); // string
console.log(typeof num); // number
console.log(typeof bool); // boolean
Copy the code

The null type detection bug has been around for over 20 years and could cause more bugs if fixed, so it will not be fixed. So the way we determine null needs to be modified! a && typeof a === ‘object’

instanceof

This is a value that represents whether or not an object is built, so you’ll find that the underlying data type doesn’t work.

console.log(obj instanceof Object); // true
console.log(bigint instanceof BigInt); // false
console.log(sym instanceof Symbol); // false
console.log(str instanceof String); // false
console.log(num instanceof Number); // false
console.log(bool instanceof Boolean); // false
Copy the code

The basic type of boxing is generally in. Operator. Such as STR. CharAt (0)

Object.prototype.toString.call

This method can accurately obtain specific types, including object subtypes such as function and array

const arr = [];
const func = () = > {};

const getType = (value) = > Object.prototype.toString.call(value).slice(8, -1);

console.log(getType(arr)); // Array
console.log(getType(func)); // Function
console.log(getType(str)); // String
console.log(getType(num)); // Number
console.log(getType(bool)); // Boolean
console.log(getType(sym)); // Symbol
console.log(getType(bigint)); // Bigint
console.log(getType(null)); // Null
console.log(getType(obj)); // Object
console.log(getType(undefined)); // Undefined
Copy the code

Values and types

Variables don’t have types in JavaScript, only values. Because variables can be changed to other types of values at any time.

Undefined and undeclared

Undefined is declared in a scope but not yet assigned, and undeclared is undeclared. These two are different.

// undefined can use this judgment
let a;

if (a) {
  // ...
}

// data are declared undeclared
if (b) {
  //Uncaught ReferenceError: b is not defined
  // ...
}
Copy the code

But the odd thing about JS is that using Typeof returns the same result in both cases

let a;
typeof a; // undefined
typeof b; // undefined
Copy the code

So we can use this feature to determine whether some values are already defined or declared

if (typeof DEBUG === "undefined") {
  // ...
}
Copy the code

value

An array of

Unlike other languages, JS arrays can hold all other values and do not require a preset size. Arrays are indexed by numbers, but since arrays are objects in JS, they can also use string attributes, but not the length of the array.

const arr = [0.1.2.3];
arr["are"] = "you ok?";

arr.length; / / 4
Copy the code

And if a string can be cast to base 10, it is treated as a numeric index.

const arr = [];
arr["13"] = Awesome!;

arr.length; / / 14
Copy the code

For sparse arrays (arrays with vacant cells), some object methods of the array are skipped rather than passed undefined, such as map. The forEach, etc.

const arr1 = [0.2.3.4]
arr1.forEach(item= > console.log(item)) // 0 2 3 4
Copy the code

An array of class

Sometimes we need to convert an array of classes (a set of values indexed numerically) into a real array, such as a DOM list retrieved from a DOM query, arguments objects. We can do that

const arrayFrom = (value) = > Array.prototype.slice.call(value)
Copy the code

Or just use ES6’s new array method

const arrayFrom = Array.from
Copy the code

string

Strings are sometimes a bit like arrays because they all have methods like Length, indexOf, concat, and can also be indexed by numbers. But they are different, for example string numeric indexes can only be evaluated, not assigned

let arr = ['a'.'r'.'e']
let str = 'are'

arr[1] = 'u'
str[1] = 'u'

console.log(arr[1]) // u
console.log(str[1]) // r
Copy the code

Why does a string pass like an object when it is an underlying type? Operator to use method objects? This is because JS automatically does the boxing for us, and all the String methods we call are provided by the String function, including other underlying data types such as numbers. The same is true of Bull et al.

digital

Before Bigint, JS had only one kind of number, which already included “whole numbers” and decimal numbers with decimals. Integers are quoted because JS has no real integers. 40.00 is the same as 40. JS uses the IEEE754 standard, also known as floating point, in the double precision format (64-bit binary). As with string, numbers defined by literals can also use the methods in Number. Literals are generally defined in decimal.

let a = 666.66

a.toFixed(1) // 666.7 Round to preserve one decimal and convert it to a string
Copy the code

We can also define numbers in terms of exponents

const a = 1E3 // 1 times 10 ^ 3, which is 1000
Copy the code

Other formats are also supported

const a = 0xf3 // Hexadecimal 243
const b = 0o363 // Base 243
const c = 0b11110011 // Base 2 243
Copy the code

Problems with the IEEE754 standard

Any language that uses this standard has a hole in it

0.1 + 0.2= = =0.3 // false
Copy the code

In short, the binary floating-point numbers 0.1 and 0.2 are not quite accurate. 0.1+0.2 is actually 0.30000000000000004, so the result is false.

For JS, this Number is 2^-52. In ES6, this value is also defined in number.epsilon, so we can do this

function numbersCloseEnoughToEqual(val1, val2) {
    return Math.abs(val1-val2) < Number.EPSILON
}
Copy the code

Some extreme values of numbers

  • Maximum and minimum rendered numbers:Number.MAX_VALUEandNumber.MIN_VALUERepresent the1.798 e+308and5e-324
  • Maximum and minimum safe integers:Number.MAX_SAFE_INTEGERandNumber.MIN_SAFE_INTEGERRepresent the2 ^ 53-1and- 2 ^ 53 + 1

Special values

Null, and undefined

Null and undefined have only one value, themselves, and there is a slight difference between them.

  • null: a null value
  • undefined: there is no value

Undefined can be assigned in non-strict mode, which is a strange use. Never use it, just learn about it.

undefined = 2
Copy the code

Void operator.

Undefined is a built-in identifier, and its value is undefined unless redefined (see 👆 above), which we can get by using the void operator. The expression void XXX returns no value, so undefined is returned.

const a = Awesome!
console.log(void a) // undefined
Copy the code

Special numbers

  • NaN

    NaN does not mean a number. It is the result of a failed numerical operation, for example

    const a = 2 / 'hello' // NaN
    console.log(typeof a) // number but it is still a number...
    Copy the code

    NaN has a special point that it is not equal to itself. NaN is the only value that is not reflexive. NaN! = NaN

    So we can use this feature to determine if NaN is true.

    if(a ! = a) {// ...
    }
    Copy the code

    Or use the built-in function isNaN, but isNaN has a sore point

    const a = Awesome! / 'hello'
    
    console.log(isNaN(a)) // true
    console.log(isNaN('hello')) // true...
    Copy the code

    Obviously the string is not a NaN and it is not a number, but true is still returned. So we should all use the new Number. IsNaN in ES6 in the future.

    const a = Awesome! / 'hello'
    
    console.log(Number.isNaN(a)) // true
    console.log(Number.isNaN('hello')) // false
    Copy the code
  • Infinity

    const a = 1 / 0 // Infinity
    const b = -1 / 0 // -Infinity
    Copy the code

    In JS, 1/0 does not return an error, but Infinity or -infinity (positive number.positive_infinity and negative number.negative_infinity).

    Infinity is irreversible, which means that if you get an infinite value, that value will never become finite again

  • Zero value

    JS has two zero values, 0 and -0. Addition and subtraction do not give you negative zero, only multiplication and division give you negative zero.

    Stringing -0 yields “0”, but digitizing it the other way around yields the normal return value.

    const a = -0
    
    console.log(a.toString()) / / '0'
    console.log(JSON.stringify(a)) / / '0'
    
    const b = '0'
    console.log(JSON.parse(b)) / / - 0
    console.log(Number(b)) / / - 0
    Copy the code

A special equation

As I said, there are a lot of times when the result of the equation doesn’t necessarily match our intuition, like NaN is not equal to itself, 0 is equal to minus 0. In ES6, a new method object. is to determine whether two values are absolutely equal has been added to handle these special cases.

const a = Awesome! / 'hello'
console.log(Object.is(a, NaN)) // true

console.log(Object.is(0, -0)) // false
Copy the code

Of course, don’t use object. is when you can use == or ===, because the former are more efficient, and the latter is used only for special cases.

Value and reference

JS references refer to values, not variables. JS cannot make a variable point to another variable, but can only make the value of a variable refer to the value of another variable, that is, reference the same value.

JS reference to a value and assignment are no different in usage, completely determined by the value.

const a = 111
const b = a // assign a copy of a to b

const obj = { a: 1 }
const obj1 = obj // reference, obj1 refers to the value of obj. There is no copy operation in the middle, so both variables point to the same value.
Copy the code

So in general, assignment/passing is always done by copy for primitive types (which are all primitive types except objects) and by reference for complex types (objects). So references refer to values, not variables, and one reference cannot change the direction of another.

let arr = [1.2.3]
let cpArr = arr

arr = [4.5.6]
console.log(arr) / / (4 and 6)
console.log(cpArr) / / [1, 2, 3]

// Another example
function foo(arr) {
    arr.push(Awesome!)
    
    arr = [4.5.6]}const a = [1.2.3]
foo(a)
console.log(a) // [1,2,3,666] instead of [4,5,6]
Copy the code

Another point to note about references is that since the value of a reference is the same, changes to this value affect all variables that reference it.

const a = [1.2.3]
const b = a

a.push(Awesome!)

console.log(a, b) / /,2,3,666 [1], [1,2,3,666]
Copy the code