May 31, 2021 Article blog
1. What data types are available in JavaScript?
3. null and undefined silly can't tell?
4. Recognize the new original type Symbol
The types of data defined in the computer world are actually defined to describe the facts that exist in the real world. For example, we use people as examples:
Boolean
type in
JS
true
for yes,
false
for non;
Number
type in
JS
containing integers and floats, and some special values, such as:
-Infinity
for negative infinity,
+Infinity
for positive infinity,
NaN
for not a number;
String
type in
JS
null
and
undefined
in
JS
Symbol
type in
JS
indicating that it is unique and immutable;
Number
integer represented by Number is a range, and out-of-range data cannot be represented by
Number
so a new data
BigInt
is proposed in
ES10
that can represent the integer of any number of digits;
Boolean
Number
String
null
undefined
Symbol
and
BigInt
are the original types in
JavaScript
and one is a non-original type called an object type;
let person = {
name: 'bubuzou',
sex: 'male',
age: 26,}
Before we answer this question, let's look at how variables are stored in memory:
let name1 = 'bubuzou'
let name2 = name1.concat('.com')
console.log(name1) // 'bubuzou'
After executing the above code, we find that the value of the variable
name1
remains the same and
bubuzou
T
his illustrates the immutability of strings.
But if you look at the following code, you'll have questions:
let name1 = 'bubuzou'
name1 += '.com'
console.log(name1) // 'bubuzou.com'
You said the string was immutable, wasn't it? I
n fact, this is only the value of the variable has changed, but the strings that exist in memory remain unchanged. T
his involves the storage of variables in memory. I
n
JavaScript
variables are stored in memory in two ways: in the stack and in the heap.
So what's the difference between stack memory and heap memory?
Stack memory:
Heap memory:
After understanding that there are two ways variables can be stored in memory, let's continue to draw a diagram of the storage structure of the variables using the above string of code as an example:
Then we can describe what happened when the computer executed this code. F
irst a variable
name1
is defined and assigned a
bubuzou
which opens up a space in memory to store the string
bubuzou
and then the variable points to that memory space. T
hen execute the second line of code
letname2=name1.concat('.com')
the stitching operation here actually produces a new string
bubuzou.com
so a new piece of memory is created for the new string and the defined variable
name2
is pointed to this memory address.
So we see that the whole operation
bubuzou
this string is in the memory is actually unchanged, even in the second piece of code to perform
name1+='.com'
operation, in fact, it is only the variable
name1
points to the new string
bubuzou.com
the old string
bubuzou
still exists in memory, but after a while because the string is not referenced by the variable, so it will be garbage collection, thus freeing up the block of memory space.
Thus we conclude that the values of the original type are fixed, while the object types are combined into a complex object by the key value pairs of the original type;
Think of a question why the value of the reference type is stored in heap memory? C an it be stored in stack memory? Answer 1: Because the reference type size is not fixed, and the size of the stack is fixed, the size of the heap space can be dynamically changed, so the value of the reference type is suitable for the existence of the heap;
When we compare two variables, different types of variables behave differently:
let str1 = 'hello'
let str2 = 'hello'
console.log( str1 === str2 ) // true
let person1 = {
name: 'bubuzou'
}
let person2 = {
name: 'bubuzou'
}
console.log( person1 === person2 ) // false
We have defined two string variables and two object variables, all of which are identical in length, but the string variables are equal and the object variables are not. T
his is because in
JavaScript
prototype types are compared to whether the values in the stack are equal, and reference types are compared to whether reference addresses in stack memory are equal.
The storage model for the previous variables in memory is shown in the figure:
When a variable is copied, there is a difference between the original type and the reference type variable, so let's look at the following code:
let str1 = 'hello'
let str2 = str1
str2 = 'world'
console.log( str1 ) // 'hello'
letstr1='hello'
Before copying, a variable
str1
is defined and assigned
hello
at which point the
hello
string is allocated a piece of space in the stack memory for storage, and then the variable
str1
points to this memory address;
letstr2=str1
After copying, assign the value of
str1
to
str2
at which point a new space is opened in the stack to store the value of
str2
str2='world'
assign
str2
a new string
world
then a new piece of memory will be used to store
world
while the memory space of
str2
original value
hello
will be garbage collected after a period of time because there are no variable references;
console.log(str1)
Because
str1
and
str2
have different stack memory addresses, even if the value of
str2
is changed,
str1
is not affected.
Then let's move on and look at the replication of the reference type:
let person1 = {
name: 'bubuzou',
age: 20
}
let person2 = person1
person2.name = 'bubuzou.com'
console.log( person1.name) // 'bubuzou.com'
When the original type is copied, the value of the variable is re-assigned, as shown in the figure above: when the reference type is copied, the reference address to which the variable points is assigned to the new variable, so after
person1
and
person2
point to the same value in heap memory, so when
person2.name
is changed,
person1.name
is also changed for this reason.
Let's start with the conclusion that in
JavaScript
the arguments of all functions are passed by value.
Here's the code:
let name = 'bubuzou'
function changeName(name) {
name = 'bubuzou.com'
}
changeName(name)
console.log( name ) // 'bubuzou'
A variable
name
is defined and assigned
bubuzou
which is
name
in when the function is called, at which point a local variable
name
is created inside the function and the value of the global variable
bubuzou
passed to him, which is actually a new piece of memory to hold the value of the local variable, and then The value of the local variable is changed to
bubuzou.com
this time there will be 3 pieces of address space in memory to hold the value of the global variable
bubuzou
the original value of the local variable
bubuzou
and the new value of the local variable
bubuzou.com
After a while, because the old and new values
name
the local variables do not have variable
bubuzou
the two spaces will be reclaimed and released;
If you look at the reference type of argument, will it be different?
let person = {
name: 'bubuzou'
}
function changePerosn(person) {
person.name = 'bubuzou.com'
}
changePerosn( person )
console.log( person.name ) // 'bubuzou.com'
When the reference type is a function argument, the reference address is copied to the local variable, so the global
person
and the local variable
person
function person point to the same heap address, so once one side changes, the other party will also be changed, so at this point we can conclude that: when the function is ginseng, if the argument is a reference type then is a reference pass?
Under the example above:
let person = {
name: 'bubuzou'
}
function changePerosn(person) {
person.name = 'bubuzou.com'
person = { name: 'hello world'
}
}
changePerosn( person )
console.log( person.name ) // 'bubuzou.com'
If
person
is passed by reference, it automatically points
person
to a new object whose value has
person
been changed to
hello world
null
is a primitive type in
JavaScript
with only one value
null
representing special values such as none, empty, unknown values, and so on.
You can assign a variable a
null
directly:
let s = null
undefined
like
null
is a self-contained primitive type, meaning that a variable is defined but not assigned, the value of the variable is
undefined
:
let s
console.log( s) // undefined
Although it is not wrong to assign a variable a direct value of
undefined
in principle it is appropriate to assign a direct assignment to
null
if a variable value is undeterred or indicates empty, and it is not recommended to assign a variable a value
undefined
null
and
undefined
return
false
when making logical judgments:
let a = null, b
console.log( a ? 'a' : b ? 'b' : 'c') // 'c'
null
becomes
0
when it is converted to a number type, and
undefined
becomes
NaN
:
let a = null, b
console.log( +null ) // 0
console.log( + b ) // NaN
Symbol
value represents a unique identifier and is a newly introduced primitive type in
ES6
You can create an important value through
Symbol()
or pass in a description value whose uniqueness is that even incoming descriptions do not equal between them:
let a = Symbol('bubuzou')
let b = Symbol('bubuzou')
console.log( a === b ) // false
So isn't any two
Symbol
described the same unequi equal? T
he answer is no.
You can find or create a new
Symbol
by
Symbol.for()
let a = Symbol.for('bubuzou')
let b = Symbol.for('bubuzou')
console.log( a === b ) // true
Symbol.for()
allows you to look globally based on the incoming description, create a new
Symbol
if it is not found, and return it, so when you execute the second line of code
Symbol.for('bubuzou')
you will find the
Symbol
described globally as
bubuzou
so here
a
and
b
will be absolutely equal.
If you can find
Symbol
by description, can you find it through
Symbol
The answer is yes, but it must be a global
Symbol
and if not found,
undefined
is returned
:
let a = Symbol.for('bubuzou')
let desc = Symbol.keyFor( a )
console.log( desc ) // 'bubuzou'
However, for any
Symbol
there is a property description that
description
the description of the
Symbol
let a = Symbol('bubuzou')
console.log( a.description ) // 'bubuzou'
We know that an object's property key can be a string, but not
Number
or
Boolean
Symbol
was designed to be the property key for the object:
let age = Symbol('20')
let person = {
name: 'bubuzou',
[age]: '20', // 在对象字面量中使用 `Symbol` 的时候需要使用中括号包起来
}
A
Symbol
is
person
here as a property key, which is better than using a string as a property key?
The most obvious benefit is that if this
person
object is developed and maintained by multiple developers, it is easy to add properties to
person
with the same name, and if you use strings as property keys, that's definitely a conflict, but if you use
Symbol
as a property key, there's no problem because it's a unique identifier, so you can protect the properties of the object from accidental access or overrides.
Note that if you use
Symbol
as the property key for an object, the loop here
forin
Object.getOwnPropertyNames
or
Object.keys()
cannot get
Symbol
property key, but it can be obtained through
Object.getOwnPropertySymbols()
for (let o in person) {
console.log( o ) // 'name'
}
console.log (Object.keys( person )) // ['name']
console.log(Object.getOwnPropertyNames( person )) // ['name']
console.log(Object.getOwnPropertySymbols( person )) // [Symbol(20)]
There are two types of numbers involved in
JavaScript
the
Number
type, stored in
64
IEEE-754
as double floats, which is the number we normally use, which ranges from $2 to {52} The second type is
BigInt
which represents integers of any length, from $2 to {52} -${52}$ to -$2.{52}$.
Here we only cover
Number
numbers.
For a regular number, we can write it directly, for example:
let age = 20
But there is also a particularly large number of numbers that we are used to using the representation of scientific counting:
let billion = 1000000000;
let b = 1e9
The above two formulations mean that
1e9
means 1 x $10,9$, and if it is
1e-3
1 / $10,3$, 0.001.
In
JavaScript
you can also represent different indents with numbers, such as
10
in decimals that can be represented as
0b1010
0o12
and 0xa in binary,
0b
and
0xa
respectively, where 0b is a binary prefix,
0o
is an octal prefix, and
ox
is a hex prefix.
We can also convert between feeds using the
toString(base)
base
method, which is the cardinality of the feed, representing the decimal, which defaults to
10
system and returns a string representation of the converted value.
Like what:
let num = 10
console.log( num.toString( 2 )) // '1010'
console.log( num.toString( 8 )) // '12'
console.log( num.toString( 16 )) // 'a'
Numbers can also be called directly by method,
10..toString(2)
Here's 2.
number is not wrong, but must be 2, otherwiseSyntaxError
error will be reported. T he first point represents the decimal point, and the second is the calling method. P oint symbols are first considered part of the numeric constant, and secondly as property accesses, and if only one point is written, the computer cannot know whether this represents a decimal or a function. There are several ways to write a numeric direct call function:
(10).toString(2) // 将10用括号包起来
10.0.toString(2) // 将10写成10.0的形式
10 .toString(2) // 空格加上点符号调用
In addition to regular numbers, the
Number
type contains some special numbers:
NaN
Represents not a number, usually the result of unreasonable calculations, such as numbers divided by string
1/'a'
NaN
and any number of comparisons are
false
including himself:
NaN==NaN
returns
false
H
ow can I tell if a number is
NaN
There are four ways:
Method 1: With
isNaN()
function, this method also returns
true
to the incoming string, so the judgment is inaccurate and is not recommended:
isNaN( 1 / 'a')` // true
isNaN( 'a' ) // true
Method 2: By
Number.isNaN()
it is recommended to use:
Number.isNaN( 1 / 'a')` // true
Number.isNaN( 'a' ) // false
Method 3: By
Object.is(a,isNaN)
:
Object.is( 0/'a', NaN) // true
Object.is( 'a', NaN) // false
Method 4: N
n
NaN
by judging
n!==n
and returning
true
:
let s = 1/'a'
console.log( s !== s ) // true
+Infinity
represents positive infinity, such as the result of
1/0
calculation,
-Infinity
negative infinity, such as the result of
-1/0
+0
-0
in
JavaScript
are positive and negative, including zero, and they are absolutely equal:
console.log( +0 === -0 ) // true
console.log( 0.1 + 0.2 == 0.3 ) // false
Have you ever wondered why the above is not equal?
Because numbers are stored in binary within
JavaScript
they follow
IEEE754
standard, store a number in
64
bits, and
64
bits are separated into
1
11
and
52
bits to represent the sign, exponential, and tail digits, respectively.
For example, what is the decimal
0.1
after conversion to binary?
We manually calculate that the decimal decimal to binary decimal rule is "multiplier 2 rounding, sequential arrangement", the specific approach is: with 2 times decimal decimals, you can get the product, the integer part of the product is removed, and then use 2 times the remaining decimal part, and then get a product, and then the whole part of the product is taken out, so that until the decimal part of the product is zero, or to achieve the required accuracy.
0.1 * 2 = 0.2 // 第1步:整数为0,小数0.2
0.2 * 2 = 0.4 // 第2步:整数为0,小数0.4
0.4 * 2 = 0.8 // 第3步:整数为0,小数0.8
0.8 * 2 = 1.6 // 第4步:整数为1,小数0.6
0.6 * 2 = 1.2 // 第5步:整数为1,小数0.2
0.2 * 2 = 0.4 // 第6步:整数为0,小数0.4
0.4 * 2 = 0.8 // 第7步:整数为0,小数0.8...
After we calculate this in turn, we find that the order of the integers is
0001100110011001100....
Infinite loop, so theoretically
0.1
will be an infinite decimal
0.0001100110011001100...
, represented by scientific counting, will be
1.100110011001100...
x $2,400, but since
IEEE754
standard specifies that a number can only be
64
digits and a significant number in
52
digits, a total of 52 bits will be rounded to
1100110011001100....
This infinite number is rounded to a total of
52
digits as valid bits, T
hen the binary end trade-off rule is to look at the last digit if
1
is in place, and if it is
0
then directly rounded. S
o since the
53
digit of this string of numbers is exactly
1
the final number is
1100110011001100110011001100110011001100110011001101
1.100110011001100110011001100110011001100110011001101
x $2.-4.
1100110011001100....
Decimal-to-binary can also be
toString
console.log( 0.1.toString(2) ) // '0.0001100110011001100110011001100110011001100110011001101'
We found that
0.1
loses precision when converted into binary decimals, which is larger than the real value due to entry.
0.2
actually has this problem and there is a loss of precision, so in fact
0.1+0.2
will not be equal to
0.3
:
console.log( 0.1 + 0.2 ) // 0.30000000000000004
Is it impossible to tell if the two decimal places are equal?
The answer must be no, and trying to determine whether the two decimals
n1
and
n2
are equal can be done as follows:
Number.EPSILON
then the two numbers are equal.
Number.EPSILON
is the error accuracy in
ES6
and the actual value can be considered equal to $2.
if ( Math.abs( n1 - n2 ) < Number.EPSILON ) {
console.log( 'n1 和 n2 相等' )
}
toFixed(n)
toFixed()
will return the string, and we can turn it into a number with a dollar plus
+
let sum = 0.1 + 0.2
console.log( +sum.toFixed(2) === 0.3 ) // true
When working with numbers, you often encounter the rounding of values and string-to-number problems, and here we consolidate the foundation. Let's start with rounding:
Math.floor()
round down to get an integer:
Math.floor(2.2) // 2
Math.floor(2.8) // 2
Math.ceil()
rounded up to get an integer:
Math.ceil(2.2) // 3
Math.ceil(2.8) // 3
Math.round()
rounds the first decimal place:
Math.round(2.26) // 2
Math.round(2.46) // 2
Math.round(2.50) // 3
Number.prototype.toFixed(n)
like
Math.round()
rounds the number to
n
bits after the decimal point and returns as a string:
12..toFixed(2) // '12.00'
12.14.toFixed(1) // '12.1'
12.15.toFixed(1) // '12.2'
Why is
6.35.toFixed(1)
equal to
6.3
Because
6.35
is actually an infinite decimal:
6.35.toFixed(20) // "6.34999999999999964473"
So at
6.35.toFixed(1)
you get
6.3
Let's take a look at string-to-number situations:
Number(n)
or
+n
directly
n
for strict conversion:
Number(' ') // 0
console.log( +'') // 0
Number('010') // 10
console.log( +'010' ) // 10
Number('12a') // NaN
console.log( +'12a' ) // NaN
parseInt()
a non-strict conversion, parses strings from left to right, stops parsing when confronted with non-numbers, and returns parsed numbers:
parseInt('12a') // 12
parseInt('a12') // NaN
parseInt('') // NaN
parseInt('0xA') // 10,0x开头的将会被当成十六进制数
parseInt()
is used by default to parse strings in decimals, but in fact he supports the second argument passed in, indicating how many cardinality to parse the first argument:
parseInt('1010', 2) // 10
parseInt('ff', 16) // 255
How can I tell if a number is an integer? Describes two approaches:
Number.isInteger()
:
Number.isInteger(12.0) // true
Number.isInteger(12.2) // false
typeofnum=='number'&&num%1==0
function isInteger(num) {
return typeof num == 'number' && num % 1 == 0
}
In addition to the original type, there is a particularly important type: the reference type. T
he elevation describes him as a reference type, a data structure that organizes data and functionality together.
By far the most reference type we've seen is
Object
and there are two ways to create an
Object
new
operator:
let person = new Object()
person.name = 'bubuzou'
person.age = 20
let person = {
name: 'bubuzou',
age: 20
}
In addition to
Object
there are other built-in reference types in
JavaScript
such as:
Array
array
Date
date
RegExp
regular expression
Function
function
The top of their prototype chain points to
Object
:
let d = new Date()
console.log( d.__proto__.__proto__.constructor ) // ƒ Object() { [native code] }
Let's start with the question, why do variables of the original type have no properties and methods, but are able to call methods?
let str = 'bubuzou'
str.substring(0, 3) // 'bub'
Because
JavaScript
has designed several corresponding packaging types to better manipulate the original type, they are:
Boolean
Number
String
The execution of the above string of code is actually like this:
In code:
let str = new
String('bubuzou')
str.substring(0, 3)
str = null
The original type call function is actually an automatic boxing operation, the original type into a wrapper type, and then in fact the original type and the packaging type are fundamentally different, the original type is the original value, and the wrapper type is an instance of the object:
let str1 = 'bubuzou'
let str2 = new String('bubuzou')
console.log( str1 === str2 ) // fasle
console.log( typeof str1 ) // 'string'
console.log( typeof str2 ) // 'object'
There is actually a boxing operation, that must also have unboxing operations, the so-called unboxing is the packaging type into the original type of process, also known as
ToPromitive
to see the following example:
let obj = {
toString: () => { return 'bubuzou' },
valueOf: () => { return 20 },
}
console.log( +obj ) // 20
console.log( `${obj}` ) // 'bubuzou'
When unboxing, the
toString()
and
valueOf()
methods of the wrapper type are tried by default, and the order of
hint
calls varies, and if
hint
is
string
toString()
is called first, otherwise
valueOf()
is called first.
By default, an
Object
object has
toString()
and
valueOf()
methods:
let obj = {}
console.log( obj.toString() ) // '[object Object]'
console.log( obj.valueOf() ) // {},valueOf会返回对象本身
Javascript
is a weak type of speech, so type conversions often occur when working on variables, especially implicit type conversions, which can make code execution unexpected, such as the following code, can you understand the results of its execution?
[] + {} // '[object Object]'
{} + [] // 0
So we need to know the rules for type conversion, and here's a table that lists common values and types and post-conversion results for informational purposes only.
We usually write code should try to make the written code easy to understand, so that others can read after you know what you are going to do, so when judging the type should try to show the processing. For example, if you turn a string into a number, you can do this:
Number( '21' ) // 21
Number( '21.8' ) // 21.8
+'21' // 21
Turning a number display into a string can do this:
String(21) // '21'
21..toString() // '21'
The display can be converted to a Boolean type as this:
Boolean('21') // true
Boolean( undefined ) // false
!!NaN // false
!!'21' // true
In addition to the above, there are some cold operations on type conversion that sometimes work: get the number of milliseconds of the current time directly with a dollar plus operator:
+new Date() // 1595517982686
Transfer the results of the operation directly to the Boolean type with the
~
indexOf()
let str = 'bubuzou.com'
if (~str.indexOf('.com')) {
console.log( 'str如果包含了.com字符串,则会打印这句话' )
}
~~
an integer with a character or number is slightly different from
Math.floor()
~~21.1 // 21
~~-21.9 // -21
~~'1.2a' // 0
Math.floor( 21.1 ) // 21
Math.floor( -21.9 ) // -22
Implicit type conversion occurs at the runtime of
JavaScript
usually caused by some operator or statement, in the following cases:
if(..)
The condition in the statement determines the expression.
for(..;..;..)
The condition in the statement determines the expression (second).
while(..)
a
nd
do..while(..)
The condition in the loop determines the expression.
?:
The condition in the judgment expression.
||
&&
or) and (logic and) (as a conditional expression)
if (42) {
console.log(42)
}
while ('bubuzou') {
console.log('bubuzou')
}
const c = null ? '存在' : '不存在' // '不存在'
The non-Boolean values in the example above are implicitly cast to Boolean values for conditional judgment. S
pecial attention should be paid to
||
and .
&&
operators.
||
The procedure is to evaluate the left side only when the value on the left returns
false
and return it as the final result, with effects such as
a?a:b
const a = 'a' || 'b' // 'a'
const b = '' || 'c' // 'c'
The procedure for
&&
is to evaluate the right side only when the value on the left returns
true
and return the value on the right as a result, similar to the effect
a?b:a
const a = 'a' && 'b' // 'b'
const b = '' && 'c' // ''
-*/
takes precedence over non-numeric types to number types, but is special for
+
String
type, it is recognized as a string stitching, and the other side is converted to a string type first.
Number
type and the other side is the original type, the original type is converted to
Number
type.
Number
type and the other side is a reference type, the reference type and
Number
type are stitched after converting the reference type to a string.
42 + 'bubuzou' // '42bubuzou'
42 + null // 42
42 + true // 43
42 + [] // '42'
42 + {} // '42[object Object]'
Relaxed equivalement
==
and strict equivaleity
===
often asked during interviews, and the answer is generally
==
to determine whether the values are equal, and to determine whether the types are equal in addition to whether the values will be equal, the answer is not entirely correct, and the better answer is: .
===
==
===
So
==
type conversion work?
1, the number and string ratio, the string will be converted to a number for comparison:
20 == '20' // true
20 === '20' // false
2, other types and Boolean type comparison, Boolean type will first be converted to a number to compare,
true
to the number
1
false
to the number
0
note that this is a very error-prone point:
'bubuzou' == true // false
'0' == false // true
null == false // false,
undefined == false // false
[] == true // false
['1'] == true // true
So when writing code for judgment, be sure not to write it as
x==true
or
x==false
but as a direct
if(x)
judgment.
3,
null
and
undefined
: the result of
null==undefined
comparison is
true
except that the comparison values for
null
undefined
and any other results are
false
It can be assumed that
null
and
undefined
can be implicitly typed to each other in the case of
==
null == undefined // true
null == '' // false
null == 0 // false
null == false // false
undefined == '' // false
undefined == 0 // false
undefined == false // false
4, the original type and reference type comparison, the reference type will first
ToPromitive
converted to the original type and then compared, the rule refers to the unboxing operation described above:
'42' == [42] // true
'1,2,3' == [1, 2, 3] // true
'[object Object]' == {} // true
0 == [undefined] // true
5, special value
NaN == NaN // false
+0 == -0 // true
[] == ![] // true,![]的优先级比==高,所以![]先转成布尔值变成false;即变成[] == false,false再转成数字0,[]转成数字0,所以[] == ![]
0 == '\n' // true
JavaScript
has six original types,
null
undefined
boolean
number
string
Symbol
and so on, and we can use
typeof
to determine what the value is, returning a string representation of the type:
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof 42 // 'number'
typeof "42" // 'string'
typeof Symbol() // 'symbol'
But there is one exception to the original type,
typeofnull
gets 'object', so we can't get an accurate answer when we type the original value with
typeof
so how do we tell if a value is
null
type?
let o = null
!o && typeof o === 'object' // 用于判断 o 是否是 null 类型
What's the difference
undeclared
undefined
The former is a variable that is defined in scope but notundeclared
while the latter is a variable that is notundefined
in scope;
typeof
can judge the original type, so can it also judge the reference type?
typeof [] // 'object'
typeof {} // 'object'
typeof new Date() // 'object'
typeof new RegExp() // 'object'
typeof new Function() // 'function'
From the above results we can draw the conclusion that
typeof
can
function
be correctly judged when judging a reference type, and nothing else can correctly judge exactly what reference type is.
We know that
typeof
can only detect some of the original types, and there is nothing we can do about reference types.
JavaScript
provides an operator
instanceof
so let's see if he can detect the reference type:
[] instanceof Array // true
[] instanceof Object // true
We found that the array is an instance of
Array
and an instance of
Object
because the end point of the reference type prototype chain is
Object
so
Array
is naturally an instance of
Object
So let's conclude:
instanceof
use to detect reference types doesn't seem like a very reliable choice either.
We can use
Object.prototype.toString.call()
to detect the type of any variable value:
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(20) // '[object Number]'
Object.prototype.toString.call('bubuzou') // '[object String]'
Object.prototype.toString.call(Symbol()) // '[object Symbol]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call(function(){}) // '[object Function]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(new RegExp()) // '[object RegExp]'
Object.prototype.toString.call(JSON) // '[object JSON]'
Object.prototype.toString.call(MATH) // '[object MATH]'
Object.prototype.toString.call(window) // '[object RegExp]'
The article comes from the public number: The sea I'm coming, author Bran
The above is
W3Cschool编程狮
about
the junior high school front end must know the JS data type
of the relevant introduction, I hope to help you.