1. How many data types are there?

In JavaScript, each value belongs to a certain data type, of which there are currently eight:

  1. String: The value is immutable

  2. Number: includes integers and decimals, with numerical accuracy.

  3. Boolean: Only true and false are available.

  4. Null: Used as an initial value and to represent an empty object, which is 0 when converted to a value.

  5. Undefined (undefined) : Undefined is the default value of an unassigned variable and the default value returned by a function. When converted to a value, it is NaN.

  6. Object: A combination of values.

  7. Symbol: New in ES6 (ES2015), unique values are used to solve the problem of conflicting object attribute names.

  8. Bigint: new in ES11 (i.e. ES2020), the form of a number followed by n, such as 123n, used to solve the accuracy of js integers (decimal or not solved 😂).

2. Primitive types

In JavaScript, string, number, and Boolean are usually treated as primitive data types. They are the most basic data types and cannot be divided into different types.

Null and undefined are generally treated as two special values. JavaScript designer Brendan Eich originally thought of null as an empty object that could automatically be converted to 0, so he decided that undefined values should be represented by something else, hence undefined and NaN when converted to a value.

Undefined is not a keyword and can be used as a variable name, but the value is always undefined. There is only one null value, and the storage space is all 0. All variables assigned with a null value actually point to the same NULL.

As the JavaScript standard ECMAScript (ES) continues to be updated, symbol and Bigint can also be considered primitive.

All primitive types store values.

3. Compound types

Objects are the most complex data types. They are often composed of multiple primitive types, known as compound types.

Objects can be subdivided into three subtypes:

  1. Objects in the narrow sense, such as {}, are also objects in our common sense.

  2. Array: [], for example, differs from the narrow object in the organization of data.

  3. Function: Function (){}, as a data type, can be assigned to variables, laying the foundation for JavaScript functional programming.

Compound types store addresses (Pointers).

4. How to determine the data type of a value?

There are three ways to determine the data type of a value in JavaScript:

  1. The typeof operator

  2. The instanceof operator

  3. Object. The prototype. The toString method

(1) Typeof operator

The typeof operator can return a data typeof a value.

typeof ' ' // "string"
typeof 1 // "number"
typeof 1.1 // "number"
typeof true // "boolean"
typeof null // "object"
typeof undefined // "undefined"
typeof {} // "object"
typeof [] // "object"
typeof function(){} // "function"
typeof Symbol(a)// "symbol"
typeof 1n // "bigint"
Copy the code

From above, we can see several special cases when the Typeof operator returns a data type:

Case 1:

typeof null // "object"
Copy the code

Null is not an object type, but typeof NULL returns object. This is due to the history of JavaScript development. Specifically, there are two reasons:

  1. In the first version of the JavaScript language in 1995, there were only five data types (object, integer, floating point, string, and Boolean). Null was used as a special value of object types, but it was later separated as a primitive type and kept for compatibility with previous code.

  2. For the sake of performance, the 32-bit system used at the beginning of JavaScript stores the type information of variables in low places. For example, the beginning of 000 represents an object, while null all represents 0, so the type is judged as object.

So if v is defined, the most convenient way to check whether it is null is:

if(v === null){

}
Copy the code

Situation 2:

typeof undefined // "undefined"
Copy the code

Undefined is the default value for declaring only unassigned variables. It is not a keyword and can be used as a variable name. We can use typeof to determine whether a variable is declared or not. For example:

v // ReferenceError: v is not defined
typeof v // "undefined"

if(typeof v === "undefined") {console.log("Variable v undeclared");
}
Copy the code

Case 3:

typeof [] // "object"
typeof function(){} // "function"
Copy the code

Here typeof gets an array of type object, mainly to emphasize that in JavaScript, an array is essentially a special kind of object.

The type of the function is function, which is quite different from ordinary objects, so no object is returned.

If you want to distinguish between narrowly defined objects and arrays, use Typeof.

(2) Instanceof operator

Instanceof returns a Boolean value indicating whether the object is an instanceof a constructor.

That is, we can use the instanceof operator to determine the specific type of an object, such as an array:

[] instanceof Array // true
/ / is equivalent to
Array.prototype.isPrototypeOf([])
Copy the code

Indicates that the Array object [] is an instance of the constructor Array, so returns true.

Since Instanceof checks the entire prototype chain, the same instance returns true for multiple constructors, such as:

var d = new Date(a); dinstanceof Date // true
d instanceof Object // true
Copy the code

Instanceof checks if the constructor’s prototype is in the prototype chain. For all objects such as o, instanceof Object is true because Object’s prototype is at the end of the prototype chain. There is a special case:

var o = Object.create(null); // There is only null in the prototype chain for object O
typeof o // "object"
o instanceof Object // false
Copy the code

Instanceof Object returns false when there is null in the Object’s prototype chain.

The instanceof operator also checks in the constructor to see if the new command is used to run the function:

function MyObj(name){
    if(this instanceof MyObj){
        this.name = name;
    }else{
        return newMyObj(name); }}Copy the code

Note that the instanceof operator applies only to objects, not to values of primitive types. But if you must use it to determine primitive types, you can also use custom instanceof behavior to do this, for example:

class MyString{
    static [Symbol.hasInstance](str){
        return typeof str === "string"; }}"" instanceof MyString // true
Copy the code

This also shows that Instanceof is not 100% trustworthy. 😂

(3) the Object. The prototype. The toString method

Object. The prototype. The role of the toString method is to return objects of type string, such as:

var a = {};
a.toString(); // "[object Object]"
Copy the code

However, toString methods are often overridden. For example, strings, arrays, functions, and dates all have their own custom toString methods, as follows:

"123".toString(); / / "123"
[1.2.3].toString(); / / "1, 2, 3"
(function(){}).toString(); // "function(){}"
new Date('the 2020-02-02 02:02:02').toString(); // Sun Feb 02 2020 02:02:02 GMT+0800
Copy the code

So, in order to specify the type of the Object (such as o) string, use the Object. The prototype. The toString, for specified Object operation, requires the use of a function call or apply method, as follows:

Object.prototype.toString.call("123"); // "[object String]"
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function(){}); // "[object Function]"
Object.prototype.toString.call(/ 123 /); // "[object RegExp]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(Symbol()); // "[object Symbol]"
Object.prototype.toString.call(123n); // "[object BigInt]"
Copy the code

Can be found from above, through the Object. The prototype. ToString. Call method can get well corresponding to each data type string, more accurate than the typeof and instanceof. Use this to write a better type determination function:

var myType = function(o){
    var str = Object.prototype.toString.call(o);
    var type = str.match(/\[object (.*)?\]/) [1].toLowerCase();
    return type;
}

myType("123") // "string"
myType({}); // "object"
myType([]); // "array"
/ /...
Copy the code

Note that the Object. The prototype. ToLocaleString, can’t do not return objects of type string, but the Object according to certain rules after converted to string output. The array.isarray () method is a good way to check if it is an Array.

5. Data type conversion

JavaScript is a dynamically typed language. Variables have no type restrictions and can be assigned any type of value at any time.

Since the type of a variable is indeterminate, manual casts are sometimes required, and in some cases automatic casts of the data type also occur.

(1) Cast to string

You can use the String function to convert any type of value to a String.

When the original value is converted to a string, the resulting string is basically the literal equivalent, with only the values normalized:

String('abc'); // "abc"
String(123); / / "123"
String(12.00); / / "12"
String(1e2); / / "100"
String(NaN); // "NaN"
String(true); // "true"
String(false); // "false"
String(null); // "null"
String(undefined); // "undefined"
String(Symbol()); // "Symbol()"
String(123n); / / "123"
Copy the code

When converting an object to a string, the toString method of the object itself is called first. If the value is not the original value, the valueOf method of the original object is called. If it is not the original value, an error is reported. As long as the original value is obtained, the original value is returned as a string.

/ / Object. The prototype. The toString () returns the type of Object string
String({}); // "[object Object]"

// array.prototype.toString () converts each element of the Array to a string and concatenates it with a comma (,)
String([1."abc"{}]);// "1,abc,[object Object]"
Copy the code

Note that the toString method of an array converts null and undefined to an empty String, unlike the result of String().

(2) Cast to number

You can use the Number function to convert values other than those of type Symbol to numeric values.

When the original value is converted to a numeric value, the result is as follows:

Number(' '); / / 0
Number('123'); / / 123
Number('123.45'); / / 123.45
Number('123abc'); // NaN
Number(123); / / 123
Number(true); / / 1
Number(false); / / 0
Number(null); / / 0
Number(undefined); // NaN
Number(Symbol()); // TypeError: Cannot convert a Symbol value to a number
Number(123n); / / 123
Copy the code

When converting an object to a value, the valueOf method of the object is first called. If it does not get the original value, the toString method of the original object is called. If it does not get the original value, an error is reported. As long as the original value is obtained, it is converted to a numeric value and returned.

// Narrow object valueOf returns the object itself, so continue calling toString, resulting in "[object object]", which is converted to a value to get NaN
Number({}); // NaN

// Again, the object returned by valueOf of the array can only be called toString to get "", which is converted to a value to get 0
Number([]); / / 0
Number([5]); / / 5
Number([5.6]); // NaN
Copy the code

(3) Cast to Boolean (Boolean)

Boolean functions can be used to convert any value to a Boolean value. The rules are relatively simple.

The following values are false when converted to booleans:

Empty string (“”, “) zero (0, +0, -0) non-numeric (NaN) False value (false) null undefined

All other values are true when converted to booleans.

Boolean(' '); // false
Boolean('abc'); // true
Boolean(0); // false
Boolean(NaN); // false
Boolean(false); // false
Boolean(true); // true
Boolean(null); // false
Boolean(undefined); // false
Boolean({}); // true
Boolean([]); // true
Boolean(new Boolean(false)); // true
Copy the code

(4) Automatic conversion

Automatic casting is based on casts. JavaScript automatically casts data types in the following situations.

Case 1: Addition operation (+)

The addition operator (+) is used to find the sum of two numeric values, whereas JavaScript allows non-numeric addition, with automatic conversion of types.

When the two operands are both numeric, the normal numeric addition is performed:

1 + 1 / / 2
Copy the code

When both operators are strings, the addition operator becomes the concatenation operator to concatenate strings:

'123' + 'abc' // "123abc"
Copy the code

When one operand is a string and the other is a non-string, the non-string is automatically converted to a string for concatenation:

'1' + 23; / / "123"
23 + '1'; / / "231"
'1' + true; // "1true"
'1' + false; // "1false"
'1' + null; // "1null"
'1' + undefined; // "1undefined"
'1' + {}; // "1[object Object]"
'1' + ['2'.3.true{}];// "123true[object Object]"
Copy the code

When there is an object in the operand, the object is automatically converted to the original value and then added:

Normally, the object is converted to the original value to get a string, so you end up concatenating strings

1 + {}; // "1[object Object]"
1 + ['2']; / / "12"
Copy the code
Case 2: Arithmetic operations other than case 1

With the exception of case one, all types of value operations, including unary operators, automatically convert values to numeric values.

'5' - '2'; / / 3
'5' * '2'; / / 10
'5' - 2; / / 3
'5abc' - 1; // NaN
true - 1; / / 0
false - 1; // -1
'5' * []; / / 0
null + 1; / / 1
undefined + 1; // NaN
+'abc'; // NaN
+'123'; / / 123
-'123'; / / - 123
+true; / / 1
-true; // -1
+false; / / 0
-false; / / - 0
Copy the code
Case 3: Conditional judgment (if, while) and Boolean operation (! , &&, | |,? 🙂

When a Boolean value is expected, it is automatically converted to a Boolean value.

if(' '&&! []) {console('Empty string converted to Boolean false, never executed here');
}
Copy the code
Case 4: comparison operation (>, <, >=, <=, ==,! === =! = =)

When non-equality comparisons (>, <, >=, <=) are made, Unicode code points are compared by character if both operands are strings:

'a' > 'A' // true
'ab' > 'a' // true
Copy the code

If an operand is not a string, the original value is converted to a numeric value for comparison:

'2' > 1 // true
true > false // true
2 > true // true
Copy the code

If one of the operands is an object, the object is converted to the original value, and then the judgment is made according to the above situation:

5 > ['4'] // true
[2] > '11' // true
Copy the code

Note that NaN is false when compared to any value:

NaN > 0 // false
NaN> =NaN //false
1 > NaN // false
Copy the code

When equality is compared (==,! === =! ==), equality is not the same as strict equality.

Strict equality (===) verifies whether the types are consistent and does not perform type conversion. If so, then the original values compare values and objects compare addresses are consistent:

1= = ='1' // false
1= = =1 // true
+0= = = -0 // true= = = {} {}// false
var o1 = {};
var o2 = o1;
o1 === o2 // true
Copy the code

Note that NaN is false when compared to any value

Equal (==) If two operands are of the same type, they are the same as strictly equal (===). Otherwise, the original value is converted to a numeric value, and objects are converted to the original value and then compared according to the circumstances:

1= ='1' // true
1= =true // true
0= =false // true
0= =' ' // true
[1.2] = ='1, 2,' // true
Copy the code

Note that null and undefined are true only when compared to themselves or between them, otherwise false

null= =null // true
undefined= =undefined // true
null= =undefined // true
Copy the code

(after)