preface

JavaScript is weakly typed, or dynamically typed, which means that you don’t need to declare the type of a variable in advance; the type is automatically determined as the program is running. This means that you can use the same variable to hold different types of data:

var data = 5 // data is Number now
data = '5' // data is String now
data = true // data is Boolean now
.......
Copy the code

I believe that whether in the process of learning or writing business, more or less will encounter similar to – how to judge the data type of this problem. Especially in interviews, you’re often asked — name the ways you can identify arrays, what types of data do you know, and so on.

Although it seems that it is only a method to judge the data type, but involves the data type, prototype chain and other VARIOUS JS foundation, no more words, directly start.

The data type

The latest ECMAScript standard defines eight data types:

  • Primitive types in 7:
    • Boolean
    • Null
    • Undefined
    • Number
    • BigInt
    • String
    • Symbol
  • Object

The original value

— I’m actually learning about raw values for the first time

All types (basic types) except Object are immutable (the value itself cannot be changed). For example, if a string in JS is immutable (a js operation on a string returns a new string, but the original string has not been changed), we call the values of these types “primitive values.”

Boolean

For Boolean types, there are always only true and false values.

Null

Null is a literal; unlike undefined, it is not a property of a global object. Null is a missing identity indicating that the variable does not point to any object. It might be better to think of null as an object that has not yet been created.

In the API, NULL is often used where the return type should be an object, but there is no associated value.

Undefined

A variable that is not assigned will have a default value of undefined; Undefined is a property of the global object.

Number

According to the ECMAScript standard, there is only one numeric type in JavaScript: values (-(2^ 53-1) to 2^ 53-1) based on the IEEE 754 standard in the double precision 64-bit binary format. It doesn’t give an integer a particular type. In addition to being able to represent floating point numbers, there are some signed values: +Infinity, -infinity, and NaN (non-numerical, not-a-number).

BigInt

With BigInt, you can safely store and manipulate large integers. Often created by appending n to the end of an integer or by calling a constructor.

const a = BigInt('43243242424242424242342432')
// 43243242424242424242342432n

const b = 43243242424242424242342432n
// 43243242424242424242342432n
Copy the code

String

The length of a string is the number of its elements. Once a string is created, it cannot be modified. However, a new string can be created based on the operation of the original string. Such as:

  • String.concat() Concatenates a String

Insert a question: why can ‘1’.tostring () be called?

let a = new Object('1'); a.toString(); console.log('-----a',a); [String: '1'] / / a = null. The console log (' -- -- -- -- -- a final ', a); // nullCopy the code
  • Step 1: Create an Object class instance. Notice why it’s not a String? Because of the presence of Symbol and BigInt, calling new on both of them will cause errors, and the current ES6 specification does not recommend using new to create wrapper classes for basic types.
  • Step 2: Call the instance method.
  • Step 3: Destroy the instance immediately after executing the method.

Symbol

Symbol is a basic data type added to ES6. This can be created by calling the built-in function Symbol(), which dynamically generates an anonymous, globally unique value.

const a = Symbol();
const b = Symbol();
a === b // false

const c = Symbol('c'); // Symbol(c)
Copy the code

You cannot use new for the Symbol stack because Symbol is a primitive data type, not an object. You can take a string as an argument to provide a description for the newly created Symbol, which can be displayed on the console or as a string for easy identification.


The most important use of Symbol is to prevent the key of an object from being overwritten.

The difference between basic data and reference data

Basic data type
  • Access by value allows you to manipulate the actual value stored in the variable
  • The value is saved inStack memoryTakes up a fixed amount of space
Reference data type
  • Values of reference types are accessed by reference
  • Objects stored in the heap memory cannot directly access the memory space of the operation object

Back to the topic, here’s a way to determine data types 👇


typeof

typeof '5' // string
typeof 5 // number
typeof null // object
typeof undefined // undefined
typeof true // boolean
typeof Symbol('5') // symbol
typeof 5n // bigint
typeof new Object(); // object
typeof new Function(); // function

Copy the code

The above examples return the correct type for the basic data types except for null, which returns object. The call to NULL is null because

  • Null is considered an empty object, so object is returned
  • Because any object will be converted to binary, null converted to binary means all zeros, if the first three are zeros, JS will treat it as an object, this is a legacy of the early JS bug

So the typeof:

  • Applies to determining (except null) base types,
  • Determine the reference type, except that function returns object

instanceof

  • Can only be used to judgeWhether the variable has a prototype property on the prototype chain (whether the two objects belong to the prototype chain), does not necessarily get the specific type of the object
  • Instanceof does not apply to values that determine the original type. It can only be used to determine whether an object is dependent
[] instanceof Array; // true
[] instanceof Object; // true

function Person() {};
const person = new Person();

person instanceof Person; // true
person instanceof Object; // true
Copy the code

[] instanceof Array is true.

  • First, []. Proto’s prototype points to array. prototype, indicating that both objects belong to the same prototype chain, returning true
  • Again, you can see from the codeperson instanceof PersonAlso returns true. So whyperson instanceof ObjectOr true?
  • This is based on the principle of the prototype chain: start with the prototype of the constructor of the instance Object, and look up until you find the top of the prototype chain, object.prototype. If not, null is returned
  • As you can see, person and Object are part of the prototype chain, so return true

Note: Null object {} is a problem

let obj1 = {}
console.log(obj1 instanceof Object) // true

let obj2 = Object.create(null)
console.log(obj2 instanceof Object) // false

let obj3 = Object.create({})
console.log(obj3 instanceof Object) // true

Copy the code

constructor

Principle: Every instance object can access its constructor via constructor. This is also based on the principle of the prototype chain.

'5'.__proto__.constructor === String // true [5].__proto__.constructor === Array // true undefined.__proto__.constructor  // Cannot read property '__proto__' of undefined null.__proto__.constructor // Cannot read property '__proto__' of undefinedCopy the code

Since undefined and null are invalid objects and therefore have no constructor property, they cannot be determined in this way.

toString

  • Object. The prototype. The toString method returns the Object type string, and therefore can be used to judge the type of a value.

  • For instance objects may be custom toString method, will cover the Object prototype. ToString, therefore, when using, had better add call

  • All data types can be detected using this method, and it is very accurate

Object.prototype.toString.call('5') // [object String]
Object.prototype.toString.call(5) // [object Number]
Object.prototype.toString.call([5]) // [object Array]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]

Copy the code

conclusion

  • Typeof is suitable for the detection of basic types and functions, and cannot determine null and object
  • Instanceof is suitable for custom objects. It can also be used to detect native objects. It is invalid when detecting between different iframes and Windows
  • Constructor can judge almost all types except null and undefined, but constructor is easy to modify and cannot be used across iframe
  • Tostring can determine all types, which can be encapsulated as a universal DataType() to determine all data types