preface

You wish the world, I wish you no bugs. Hello everyone! I’m Lin Dull!

This issue to bring you is an article about JS data type conversion, the main cause is a few days ago in the brush type conversion problem suddenly feel their understanding is not deep enough ah, for what [] ==! [],! {} == [] this kind of questions are always half-knowledge, forget forget to remember.

This bothered me so much that I decided to give myself some great information, to thoroughly understand their conversion mechanism and then come up with a few devil questions to test myself.

At the time of writing is also pretty tangled, began to write a version of all topics, but later found that if all topics do not speak of its principle, some readers may be a face mengbi… So later I also added about toString, valueOf, toPrimitive detailed analysis, and then with some clear flow chart, and strive to be able to conversion process said clearly 😁.

Shot to play before him, however, because of the front section 1-3 are some conversion between the base type, is not difficult, so I won’t spend too much space on it, probably from the fourth quarter began to slowly a little in taste, [YinXiao ~], feel confident in conversion between the base type of friend can jump straight to the fourth quarter to see oh.

Hopefully your mind isn’t thinking “pale yellow dresses… Fluffy hair…”

OK👌, check it out By reading you can learn:

  • Other data types to Boolean values
  • Original value to string
  • Convert the original value to a number
  • Primitive value to object (wrapper object of primitive type)
  • toString
  • Symbol.toStringTag
  • valueOf
  • The execution mechanism of ToPrimitive
  • Object to string
  • Object to number

(write in the process, see yui greatly also published an article on type conversion hu “JavaScript in-depth headache type conversion (on)”, over, do… Have I reached the point where I can relate to the big boys?

In addition, the “data type conversion” series is divided into two articles to write, this one is mainly to explain the String(), Number() such conversion, for the operation symbol +, == such conversion and some advanced use of toPrimitive I will put in the next article. Hee hee, still say, step by step.

Series is introduced

The “Data type Conversion” series consists of two articles:

  • Data type conversion from 206 console.log()
  • Data type conversion from 206 console.log()

It is recommended to read them in order, and the two articles will help you fully understand casts 😁.

1. Convert other data types to Booleans

The case of converting to booleans is simple.

When we use Boolean() to convert, we have the following conversion rules:

The parameter types The results of
False, undefined, null, +0, -0, NaN, “” false
Except in the case above true

(Also note that Boolean() is false if no arguments are passed.)

1.1 Digital Transfer to Boolean value

To convert numbers to booleans, just remember:

  • In addition to0, -0, NaNThese three are converted to zerofalse, the other ones aretrue.

1.1.1 subject to a

console.log(Boolean(0))
console.log(Boolean(0))
console.log(Boolean(NaN))

console.log(Boolean(1))
console.log(Boolean(Infinity))
console.log(Boolean(-Infinity))
console.log(Boolean(100n))
console.log(Boolean(BigInt(100)))
Copy the code

Remember the above rule 👆, here I tried bigInt also, found that it is true.

So the answer is:

console.log(Boolean(0)) // false
console.log(Boolean(0)) // false
console.log(Boolean(NaN)) // false

console.log(Boolean(1)) // true
console.log(Boolean(Infinity)) // true
console.log(Boolean(-Infinity)) // true
console.log(Boolean(100n)) // true
console.log(Boolean(BigInt(100))) // true
Copy the code

1.2 Converting a String to a Boolean value

String booleans are also easy, just remember:

  • Except for empty strings""fortrue.

1.2.1 a topic

console.log(Boolean(""))

console.log(Boolean("1"))
console.log(Boolean("NaN"))
console.log(Boolean("aaa"))
Copy the code

The special thing to notice here is “NaN”, which is not a NaN, but a string.

So the answer is:

console.log(Boolean("")) // false

console.log(Boolean("1")) // true
console.log(Boolean("NaN")) // true
console.log(Boolean("aaa")) // true
Copy the code

1.3 Other Types of Boolean values

Other types, such as null, undefined, and reference to Boolean, are also known:

  • Null, and undefinedforfalse
  • Reference types such as object, array, class array, date, and re aretrue
  • document.allIs an exception, it is in nonIEwithtypeofThe detection type isundefined, so it will be convertedfalse. (Not much)

(Thank you for your friend Xiaoming Cha’s document. All)

1.3.1 topic a

var divs = document.getElementsByTagName('div')
console.log(Boolean(null))
console.log(Boolean(undefined))

console.log(Boolean({}))
console.log(Boolean({ name: 'obj' }))
console.log(Boolean([]))
console.log(Boolean(divs))
console.log(Boolean(new Date()))
console.log(Boolean(/(\[|\])/g))

console.log(typeof document.all)
console.log(Boolean(document.all))
Copy the code

The result is:

var divs = document.getElementsByTagName('div')
console.log(Boolean(null)) // false
console.log(Boolean(undefined)) // false

console.log(Boolean({})) // true
console.log(Boolean({ name: 'obj' })) // true
console.log(Boolean([])) // true
console.log(Boolean(divs)) // true
console.log(Boolean(new Date())) // true
console.log(Boolean(/(\[|\])/g)) // true

console.log(typeof document.all) // undefined
console.log(Boolean(document.all)) // false
Copy the code

Document. all[] is an array of all tags in the document, including all elements in the document object. This array can access all elements in the document. It is undefined in non-IE browsers, so it can be used to determine if the current browser is IE, but it is rarely used now, so I won’t expand it.)

2. Convert the original value to a string

For raw value to string, there is also the following summary:

The parameter types The results of
Undefined “undefined”
Null “null”
Boolean Return “true” if the argument is true. Parameter false, return “false”
Number You can see problem 2.1
String Returns the value equal to it
Symbol “Symbol()”

Let’s do a couple of problems to reinforce it.

2.1 Converting digits to Strings

2.1.1 topic a

console.log(String(0))
console.log(String(1))
console.log(String(100))
console.log(String(NaN))
console.log(String(10n))
console.log(String(10n) === '10')
Copy the code

BigInt is treated as a number.

The answer is:

console.log(String(0)) / / '0'
console.log(String(1)) / / '1'
console.log(String(100)) / / '100'
console.log(String(NaN)) // 'NaN'
console.log(String(10n)) / / '10'
console.log(String(10n) === '10') // true
Copy the code

2.2 Boolean, Symbol into a string

2.2.1 topic a

Converting these three types to strings is relatively simple:

console.log(String(true))
console.log(String(false))
console.log(String(Symbol(1)))
Copy the code

The answer:

console.log(String(true)) // 'true'
console.log(String(false)) // 'false'
console.log(String(Symbol(1))) // 'Symbol(1)'
Copy the code

3. Convert the original value to a number

The parameter types The results of
Undefined NaN
Null + 0
Boolean If the argument is true, return 1. Argument false, return +0
Number Returns the value equal to it
String Purely numeric strings (including decimals and negative numbers, decimal numbers) are converted to the corresponding number, otherwise NaN
Symbol Error with Number() transfer

Topic 3.1 a

String, null, undefined, Symbol

console.log(Number("1"))
console.log(Number("1.1"))
console.log(Number("1"))
console.log(Number("0x12"))
console.log(Number("0012"))

console.log(Number(null))
console.log(Number("1a"))
console.log(Number("NaN"))
console.log(Number(undefined))
console.log(Number(Symbol(1)))
Copy the code

The answer is:

console.log(Number("1")) / / 1
console.log(Number("1.1")) / / 1.1
console.log(Number("1")) // -1
console.log(Number("0x12")) / / 18
console.log(Number("0012")) / / 12

console.log(Number(null)) / / 0
console.log(Number("1a")) // NaN
console.log(Number("NaN")) // NaN
console.log(Number(undefined)) // NaN
console.log(Number(Symbol(1))) // TypeError: Cannot convert a Symbol value to a number
Copy the code

It’s actually pretty easy to remember:

  • Pure numeric strings (including decimals, negative numbers, and decimal numbers) are converted to corresponding numbers
  • nullto0
  • Symbolcomplains
  • Other basic types include strings that are not pure numbers,NaN.undefinedWill be converted toNaN

3.2 the topic 2

(Boolean type to number)

It is also very simple to convert booleans to numbers in only two cases:

console.log(Number(true)) / / 1
console.log(Number(false)) / / 0
Copy the code

3.3 the title three

Another way you might use to turn numbers is to use:

  • parsetInt, converts the result to an integer
  • parseFloatConvert the result to an integer or floating-point number

When they are converted to numbers, they have several characteristics:

  • If the string starts with0 x or 0 xIn the beginning,parseIntConverts it to decimal using hexadecimal number conversion rules, andparseFloatWill be resolved as a0
  • Both of them skip any number of Spaces at the beginning of the parse and execute later
  • As many numeric characters as possible will be parsed during execution. If the character cannot be parsed, it will jump out of parsing and ignore the following content
  • If the first one is not a non-space, or the beginning is not0 x, -The number literal will eventually be returnedNaN

Let’s see some exercises 😄 :

console.log(parseInt('10')) / / 10
console.log(parseFloat('1.23')) / / 1.23

console.log(parseInt("0x11")) / / 17
console.log(parseFloat("0x11")) / / 0

console.log(parseInt("11")) / / 11
console.log(parseFloat("11")) / / 11

console.log(parseInt("1.23 a12")) / / 1
console.log(parseFloat("1.23 a12")) / / 1.23

console.log(parseInt("11")) / / 11
console.log(parseFloat("11")) / / 11

console.log(parseInt("1a12")) / / 1
console.log(parseFloat("1.23 a12")) / / 1.23

console.log(parseInt("-1a12")) // -1
console.log(parseFloat(23 ".")) / / 0.23
Copy the code

Do feel all the time now quite simple ha 😄.

4. Convert the original value to the object

Raw values, which are the underlying data types.

4.1 String object

Let’s start with an object called String, whose prototype chain looks like this:

As you can see, it is essentially a constructor, and string.__proto__ points to function.prototype.

A String can be used with new as a constructor or without new:

  • When String() is used as a constructor with the new operator, it returns a newly created String containing a StringssThe string representation (however since the introduction ofSymbolIt is not recommended after thatnew StringThis approach).
  • When String() is called without the new operator, it only calls thesConverts to the original string and returns the converted value

What do you mean 🤔️? In layman’s terms:

typeof String(1) // 'string'
typeof new String(1) // 'object'
Copy the code

Using Typeof, you can see that the types are different.

4.2 Basic Types of wrapped objects

Ha, ha, ha.

Number, Boolean;

And its “cousin” : Symbol, BigInt. 😄

Number, Boolean 🤔️

This phenomenon is distinguished by degree of similarity.

So Number, Boolean, and String can be used either with new or without new.

Symbol, BigInt can only be used without new. (Because they came out after ES6, calling new on them is an error.)

So you see this phenomenon:

console.log(Number(1)) / / 1
console.log(new Number(1)) // Number{1}
console.log(Boolean(true)) // true
console.log(new Boolean(true)) // Boolean{true}

console.log(Symbol(1)) // Symbol(1)
console.log(BigInt(1)) // 1n
console.log(new Symbol(1)) // TypeError: Symbol is not a constructor
console.log(new BigInt(1)) // TypeError: BigInt is not a constructor
Copy the code

And above the Number of {1}, Boolean {true}, it’s what I want to introduce the basic types of packing objects, also known as the basic types of wrapper classes, might as well be called the original value packaging object (there are a lot of but you should all know what it says is this meaning).

As you can see, to generate a wrapper object of the underlying datatype, just call their respective constructors using new:

console.log(new Number(1)) // Number{1}
console.log(new String('1')) // String{1}
console.log(new Boolean(true)) // Boolean{true}
Copy the code

What are the characteristics of the wrapper object of this basic type?

  • usetypeofTest it, and the result isobjectThat means it is an object
  • usetoString()This call returns a string with the original value6.8.3Will be mentioned in)

But!!!

As mentioned above, the ES6 specification currently does not recommend using new to create wrapper classes of primitive types, in order to align with Symbol and BigInt.

So what is the preferred way to create a wrapper class of primitive types now?

Well… That’s the Object constructor.

4.3 the Object ()

The Object() constructor can take a variable of any type and perform different conversions.

So there are seven basic data types, or reference data types that you can pass in.

However, I mainly want to introduce the basic datatype to object, so I will do the analysis with a few basic datatype:

console.log(new Object('1')) // String{'1'}
console.log(new Object(1)) // Number{1}
console.log(new Object(true)) // Boolean{true}
console.log(new Object(Symbol(1))) // Symbol{Symbol(1)}
console.log(new Object(10n)) // BigInt{10n}

console.log(new Object(null)) / / {}
console.log(new Object(undefined)) / / {}
Copy the code

As you can see, if you pass in the base datatype, the result will be the corresponding wrapper class, but for null and undefined they will be ignored and an empty object will be generated.

Summary – Original value to object

The original value to object is summarized as follows:

  • String, Number, BooleanThere are two ways to use it: cooperatenewUse and not cooperatenewUse, butES6The specification does not recommend usenewTo create a wrapper class for the primitive type.
  • It’s even more recommended nownew Object()To create or convert a wrapper class to a primitive type.

The basic type of wrapper object features:

  • usetypeofTest it, and the result isobjectThat means it is an object
  • usetoString()This call returns a string with the original value6.8.3Will be mentioned in)

5. Prepare for converting objects to strings or numbers

The conversion of an object to a string or number is complicated and involves a method you may not have heard of before: toPrimitive()

What it does is it takes a value and returns a value that must be of a primitive type, otherwise it will throw a type error exception.

First, an executive flow chart, let us feel despair, loneliness, loneliness, cold…

It’s a little bit complicated, but that’s fine, and you’ll understand it later. Before I go to toPrimitive(), I need to go into detail about the toString() and valueOf() methods, because that’s what toPrimitive() is all about. 😄

6. toString()

6.1 Where does toString() exist

I’ve read a lot about toString() up until now, mostly about its use, but where does it really exist?

Object. Prototype: Number, String, Boolean, Symbol, BigInt; Do they have the means themselves? Or are they on their prototype objects?

In the spirit of getting to the bottom, I printed out Number and Number. Prototype:

console.log(Number)
console.log(Number.prototype)
Copy the code

And THEN I discovered a couple of things:

  • NumberIt’s just a constructor that will print out the source code
  • Number.prototypeAnd it doestoString()
  • Number.prototype.__proto__That isObject.prototypeThere are alsotoString()

Then I tried String, Boolean, Symbol and found the same result.

In fact, it is not difficult to understand the “💦【 Why not 】 complete the 48 questions to understand the JS inheritance (1.7W words contain – back to nature)” friends know that all Object prototype chain will eventually point to Object. Prototype, is regarded as “inherited” Object instance. The toString() method can therefore be used, but will be overridden for different built-in objects to better suit their functional needs, so you can see it on Number.prototype as well.

So we can draw the first conclusion:

  • In addition toNull, and undefinedOther data types (base data type + reference data type) are present on the prototype object of the constructortoString()methods
  • Base datatype constructor on the prototype objecttoString()overwriteObjectOn the prototype objecttoString()methods

(Of course, once you see 6.9, you’ll realize that this isn’t exactly true, but most of the time we care about who can use it, not where it exists.)

6.2 Who can Call toString()

The toString() method can be called on any object except null and undefined, and usually returns the same result as String.

In fact, the most common thing to get confused about here is String and toString.

I’ve always used these two attributes haphazardly to convert a type to a string.

  • StringIs a kind ofFunctionAn object like this, it can either be used as an object, using static methods on it, or it can be used as a constructor, creating aStringobject
  • whiletoStringIt is in addition toNull, and undefinedA method that does not exist on any data type, usually returns the result andStringThe same.

Why does ‘1’.tostring () succeed? That’s because the code is actually converted to a wrapper class at runtime, like this:

var str = new Object('1');
str.toString();
str = null;
Copy the code

Process analysis:

  • createObjectInstance,sInto theString{"1"}object
  • Calling instance methodstoString()
  • Destroy the instance as soon as you’re done

But didn’t we see a String before? Why not use var STR = new String(‘1’) in the first step?

Symbol and BigInt cannot be called using new, and the ES6 specification does not recommend using new to create wrapper classes of this basic type, so we use new Object() instead.

But when we try to use 1.tostring () in our code, we find that the editor has reported an error and won’t allow us to do so.

Can’t numbers be 🤔️? There’s one thing we’ve all missed, and that’s the weird question. It is also part of the number 😂.

Such as 1.2, 1.3. So when you want to use 1.tostring (), the JavaScript interpreter will treat it as part of a number, which is equivalent to (1.)toString, which is obviously wrong code.

In that case, if I still give the code one. Was that enough? So I tried:

console.log(1.1.toString())
Copy the code

And found that it actually printed:

"1.1"
Copy the code

This again proves that 1.toString() will. Ascribe to 1 instead of toString().

Of course, it works if you use a variable to carry the number:

var num = 1;
console.log(num.toString()) / / "1"

/ / or
console.log((1).toString()) / / "1"
Copy the code

So here we just need to remember who can call toString:

  • In addition toNull, and undefinedOther basic data types and objects can be called
  • Call in using a numbertoString()Error unless the number is a decimal or a variable is used to hold the number and then call. (1.1. The toString ()orvar a = 1; a.toString();)

6.3 Call of toString()

Perhaps the most common usage is this:

Object.prototype.toString.call({ name: 'obj' }) // '[object Object]'
Copy the code

Hard knowledge point, first Object. The prototype. The toString method according to the [[class]] internal attributes of objects, returned by the “[Object” and the class and “] “string is composed of three parts.

What you mean? [[class]] What is the internal attribute 🤔️?

You can’t really think too much about it here. Just take it literally.

Well, I’ll just assume it represents one thing.

like

  • Arrays are a class of its[[class]]isArray
  • String is a class of its[[class]]isString
  • argumentsIt’s one class, it’s[[class]]isArguments

In addition, there are many kinds of [[class]], and you don’t need to remember them all, just the common, basic, and easy to understand ones.

So back to the Object. The prototype. ToString. The call () calls in this way, you can understand it now, it can help us to accurately determine whether a data type, also is to discern is an array or digital or function, or NaN. 😊

And since it returns a string like “object object”, and the preceding “[object]” string is fixed (including the space after “t”), can we wrap a method to get only “object”?

Very simple, the code:

function getClass (obj) {
    let typeString = Object.prototype.toString.call(obj); // "[object Object]"
    return typeString.slice(8.- 1);
}
Copy the code

As you can see, I named this function getClass, which corresponds to its original purpose, to get the [[class]] internal properties of the object.

In addition, after receiving the “object object” string, a. Slice (8, -1) string truncation function is used to remove the first eight characters “[object]” and the last “]”.

Now let’s take a look at some common data types:

function getClass(obj) {
    let typeString = Object.prototype.toString.call(obj); // "[object Array]"
    return typeString.slice(8.- 1);
}
console.log(getClass(new Date)) // Date
console.log(getClass(new Map)) // Map
console.log(getClass(new Set)) // Set
console.log(getClass(new String)) // String
console.log(getClass(new Number)) // Number
console.log(getClass(true)) // Boolean
console.log(getClass(NaN)) // Number
console.log(getClass(null)) // Null
console.log(getClass(undefined)) // Undefined
console.log(getClass(Symbol(42))) // Symbol
console.log(getClass({})) // Object
console.log(getClass([])) // Array
console.log(getClass(function() {})) // Function
console.log(getClass(document.getElementsByTagName('p'))) // HTMLCollection

console.log(getClass(arguments)) // Arguments
Copy the code

"Lin dull, so much, this is the people do?"

"Just remember some common ones..."

"Pa!"

6.4 Differences between ToString.call () and Typeof

👌 : ToString. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call: tostring. call

Speaking of data types, we have a Typeof, right? How is it different from toString.call()?

A review of typeof’s display rules:

  • For primitive types (i.eNumber, a string,This kind of), exceptnullCan display the correct type
  • nullMisjudged for historical reasons"object"
  • For reference types (i.eThe object, arrayThis), except that functions are displayed as"object"
  • The function will be displayed asfunction

So the disadvantage of typeof is obvious. I now have an object and an array or a date object, and I want to be careful to distinguish between them, and typeof is definitely not possible because they all get “object”.

So, using our wrapped getClass() is an obvious choice.

(Of course, those who know instanceof may also know that it is possible to judge with instanceof, but this is not far away, specifically, we can look at the three big “(suggested collection) native JS soul of the question, how many can you catch? (1)”, which has mentioned this problem in the second article. Or you can look forward to the nerdy article, which will also be covered in more detail.

6.5 Differences between toString.call() and toString()

ToString () = toString.call(); toString() = toString();

true.toString() // 'true'
Copy the code

Please be sure to distinguish true. The toString () and Object. The prototype. ToString. Call (true) this two USES:

  • true.toString()Is totrueConvert to string
  • toString.call(true)Is to obtaintrueIt’s[[class]]Internal attributes:
true.toString() // 'true'
Object.prototype.toString.call(true) // "[object Boolean]"
Copy the code

Since the use of toString.call() has been covered in more detail, the rest of the article revolves around true.tostring ().

6.6 toString() in Different Cases

So what’s the difference between calling toString() on different data types?

Here I mainly break it down into two chunks:

  • Basic data type call
  • Reference type call

6.7 Basic Data Types toString is called

For primitive datatypes, it’s super easy to call, just think of it as a string instead of its original value:

console.log('1'.toString()) / / '1'
console.log(1.1.toString()) / / '1.1'
console.log(true.toString()) // 'true'
console.log(Symbol(1).toString()) // 'Symbol(1)'
console.log(10n.toString()) / / '10'
Copy the code

6.8 Invoking toString for Reference Types

The hard part is that reference types call toString(), and we know that reference types have many classes depending on [[class]], such as Object, Array, Date, and so on.

Is toString() different from class to class 🤔️?

Yes, different versions of toString are divided into:

  • An array oftoStringThe method is to convert each item to a string and use it again","The connection
  • Ordinary objects (e.g{name: 'obj'}This type of) is converted to a string"[object Object]"
  • Function (class), reIs converted to a source string
  • The date ofA date string that will be converted to the local time zone
  • Wrapper object invocation of the original valuetoStringA string that returns the original value

Good 👌, pulled so many knowledge points, finally can go up first a few questions 😁.

(No topic to do I feel bad ~)

A 6.8.1 subject

(Array toString())

Let’s start with something simple:

console.log([].toString())
console.log([1].toString())
console.log([1.2].toString())
console.log(['1'.'2'].toString())

console.log([' '.' '].toString())
console.log([' '.' '].toString())
Copy the code

The answer:

console.log([].toString()) / / ""
console.log([1].toString()) / / "1"
console.log([1.2].toString()) / / 1, 2, ""
console.log(['1'.'2'].toString()) / / 1, 2, ""

console.log([' '.' '].toString()) / / ","
console.log([' '.' '].toString()) / / ","
Copy the code

It’s not that difficult.

One thing to note is that [].toString() has no entries in the array, so it must be an empty string.

Note also that the last two, one is a completely empty string and one is whitespace.

6.8.2 topic 2

(Other objects that are not array types)

console.log({}.toString())
console.log({name: 'obj'}.toString())

console.log(class A {}.toString())
console.log(function () {}.toString())
console.log(/(\[|\])/g.toString())
console.log(new Date().toString())
Copy the code

According to rule 2,3 and 4 at 👆 above, the answer would be:

'[object Object]'
'[object Object]'

'class A {}'
'function () {}'
'/(\[|\])/g'
Fri Mar 27 2020 12:33:16 GMT+0800 '
Copy the code

Three 6.8.3 subject

(toString() is called by the primitive wrapper object.)

The primitive value wrapper object is covered in chapter 4 of 👆 above, which is:

Number{1}
String{'1'}
Boolean{true}
Copy the code

Objects like this.

When they call the toString() method, they return a string of their original value, like this:

console.log(new Object(true).toString()) // "true"
console.log(new Object(1).toString()) / / "1"
console.log(new Object('1').toString()) / / "1"
console.log(new Object(Symbol(1)).toString()) // "Symbol(1)"
console.log(new Object(BigInt(10)).toString()) 10 "/ /"
Copy the code

Four 6.8.4 subject

(Map, Set call toString)

While doing this, I wanted to test what a Map/Set call to toString would look like.

console.log(new Map().toString())
console.log(new Set().toString())
console.log(new Array(['1']).toString())
Copy the code

What I found was:

console.log(new Map().toString()) // "[object Map]"
console.log(new Set().toString()) // "[object Set]"
console.log(new Array(['1']).toString()) / / "1"
Copy the code

This watch I’m a little stupid, how the previous two. The result is a bit like the Object prototype. ToString. The call () calls the results? If it’s an array, it follows the same rules as converting an array to a string…

Ahhhhh… It is not easy to understand some, how come there is a Map, Set.

Curiosity led me to print out the instance object new Map() :

console.log(new Map())
Copy the code

Map.prototype doesn’t have its own toString() method like Number.prototype does, but object. prototype does.

And there seems to be a property we’ve never seen before: Symbol(symbol.toStringTag), and it happens to be “Map”.

6.9 Symbol. ToStringTag

Do not understand to check, search a wave of Symbol. ToStringTag, I suddenly realized.

The Symbol. ToStringTag describes it as follows:

The symbol.toStringTag public Symbol is the string value attribute used in the default string description of the object created. It is composed of the Object. The prototype. The toString () method in internal access.

It determines what the [[class]] internal property of all the data types we mentioned earlier is.

For example, Number, we got [[class]] is Number, then I can understand the Number class and its Symbol. ToStringTag returns Number.

The Number, String, and Boolean attributes do not include symbol.toStringTag, which is returned when toString.call() is used.

New Map() : Symbol. ToStringTag () : new Map() : Symbol. ToStringTag () : Symbol. “[Object Map]” is returned.

Well, is that how we understand it?

  • There is noSymbol.toStringTagThe type of the built-in property is calledtoString()Is equivalent toString(obj)This call is converted to the corresponding string
  • There areSymbol.toStringTagThe type of the built-in property is calledtoString()Will return the corresponding label (i.e"[object Map]"Such a string)

Examples of common objects with symbol.toStringTag built-in attributes are:

console.log(new Map().toString()) // "[object Map]"
console.log(new Set().toString()) // "[object Set]"
console.log(Promise.resolve().toString()) // "[object Promise]"
Copy the code

And I found that it, like symbol. hasInstance, allows us to customize tags.

(Symbol.hasInsance is used to customize the return value of instanceof)

What are custom tags 🤔️?

That is, if we now create a class and call its instance object with toString.call(), we get the following result:

class Super {}
console.log(Object.prototype.toString.call(new Super())) // "[object Object]"
Copy the code

The resulting new Super() is an object, so it will print “[object object]”.

But now that we have symbol. toStringTag, we can change the following “Object”.

For example, let me rewrite:

class Super {
  get [Symbol.toStringTag] () {
    return 'Validator'}}console.log(Object.prototype.toString.call(new Super())) // "[object Validator]"
Copy the code

This is where symbol.toStringTag comes in handy. It allows us to customize the tag.

Symbol. ToStringTag overrides the tag of new Super(), not the tag of Super.

class Super {
  get [Symbol.toStringTag] () {
    return 'Validator'}}console.log(Object.prototype.toString.call(Super)) // "[object Function]"
console.log(Object.prototype.toString.call(new Super())) // "[object Validator]"
Copy the code

Since Super itself is still a function, only instance objects generated by Super will use our custom tags.

Summary – the toString ()

It’s a lot of stuff. Let’s sum it up and straighten it out so it’s easy to remember.

Who can call toString()?

  • In addition toNull, and undefinedOther basic data types and objects can be called, usually returning results andStringThe same.
  • Call in using a numbertoString()Error unless the number is a decimal or a variable is used to hold the number and then call. (1.1. The toString ()orvar a = 1; a.toString();)

Object. The prototype. ToString. Call () what do you use?

  • Returns an internal property of some data[[class]], can help us accurately determine a data type
  • thantypeofDetermine the data type more accurately

Call toString() for different data types

  • When a primitive data type is called, its original value is replaced with a string
  • An array oftoStringThe method is to convert each item to a string and use it again","The connection
  • Ordinary objects (e.g{name: 'obj'}This type of) is converted to a string"[object Object]"
  • Function (class), reIs converted to a source string
  • The date ofA date string that will be converted to the local time zone
  • Wrapper object invocation of the original valuetoStringA string that returns the original value
  • haveSymbol.toStringTagObjects with built-in attributes change to their corresponding labels when invoked"[object Map]"

Symbol.toStringTag

  • It’s a built-in property of some particular type, for exampleMap, Set, Promise
  • The main function is to allow us to customize the tag, modifyObject.prototype.toString.call()Return result of

7. valueOf()

ValueOf is toString() ‘s twin, 🤔️.

Because they share many of the same features, such as the toString() location mentioned earlier, we can look back at the diagram in 6.1 and see that valueOf() exists where toString() exists.

Another important reason to introduce it is that it complements toString() in object-to-base data types.

Its main functions are:

Converts an object to a value of basic data.

So we can see the difference:

  • toStringBasically, you convert an object to a string
  • valueOfBasically, the object is converted to a value of basic data

Let’s look at the basic usage of valueOf first.

7.1 Calling valueOf() for Basic Data Types

A call to a primitive data type is also simple; it simply returns the caller’s original value:

console.log('1'.valueOf()) / / '1'
console.log(1.1.valueOf()) / / 1.1
console.log(true.valueOf()) // true
console.log(Symbol(1).valueOf()) // Symbol(1)
console.log(10n.valueOf()) // 10n
Copy the code

It doesn’t seem to have changed, right, so you can check it out with the following 👇 :

var str = '1'
console.log(str.valueOf() === str) // true
Copy the code

7.2 Calling valueOf() for Reference Types

Calling valueOf() by reference type is not hard, you just need to remember:

  • Other reference type calls for non-date objectsvalueOf()The default is to return itself
  • And the date object will return oneMilliseconds since January 1, 1970.

Such as:

console.log([].valueOf()) / / []
console.log({}.valueOf()) / / {}
console.log(['1'].valueOf()) / / / '1'
console.log(function () {}.valueOf()) / / ƒ () {}
console.log(/(\[|\])/g.valueOf()) // /(\[|\])/g
console.log(new Date().valueOf()) / / 1585370128307
Copy the code

Summary – the valueOf ()

The basic usage of valueOf()

  • A basic data type call that returns the original value of the caller
  • Other reference type calls for non-date objectsvalueOf()The default is to return itself
  • And the date object will return oneMilliseconds since January 1, 1970(similar to the1585370128307).

8. toPrimitive

ToString () and valueOf(), toPrimitive…

Tears cow face 😢.

Do not be careless, however, it is the most difficult to chew that knowledge point.

Let’s look at its functional syntax first:

ToPrimitive(input, PreferredType?)
Copy the code

Parameters:

  • A parameter:inputRepresents the input value to be processed
  • Parameters of the two:PerferredType, the type to be converted. You can see that the syntax has a question mark after it to indicate that it is not required. It has only two optional values,NumberandString.

The processing of incoming parameters is more complicated. Now let’s look at the flow diagram at the beginning:

According to the flow chart, we get the following information:

  1. When the PreferredType is not passed, it is equivalent to a String if the input is of date type, and a Number otherwise.
  2. If ToPrimitive(obj, Number) is used, the procedure is as follows:
  • If obj is a basic type, return it directly
  • Otherwise, the valueOf method is called, and if a raw value is returned, JavaScript returns it.
  • Otherwise, the toString method is called, and if a raw value is returned, JavaScript returns it.
  • Otherwise, JavaScript throws a type error exception.
  1. If it is ToPrimitive(obj, String), the processing is as follows:
  • If obj is a basic type, return it directly
  • Otherwise, the toString method is called, and if a raw value is returned, JavaScript returns it.
  • Otherwise, the valueOf method is called, and if a raw value is returned, JavaScript returns it.
  • Otherwise, JavaScript throws a type error exception.

(Summary source: Yuba Hu -JavaScript Deep Headache of type conversion (1))

The diagram above at 👆 is actually quite complicated. If you are careful, you may notice that only the toString() and valueOf() methods are executed in different order in the red frame.

If the PreferredType is String, the toString() method is executed first

If the PreferredType is Number, the valueOf() method is executed first

Lin Naidai suggests that you draw this process on your draft paper first, and then do the problem to help you remember 😁.

9. Object to string

Topic 9.1 a

(Basic conversion)

Okay, goofy, I see you are talking about toPrimitive conversion process, but I don’t see any practical use.

This is… No, actually, we’ve been using it for a long time, but you probably didn’t know that.

For example, when we use String() to convert an object to a String:

console.log(String({}))
Copy the code

You all know the result:

"[object Object]"
Copy the code

But why is it that way? Look at the result and the result of the toString() call.

ToPrimitive’s conversion rules are used here.

You have a look, we change the above 👆 code into toPrimitive pseudo-code to see:

toPrimitive({}, 'string')
Copy the code

OK👌, to review the transformation rules:

  1. inputis{}, is a reference type,PerferredTypeforstring
  2. So calltoString()The method, which is equal to{}.toString()
  3. {}.toString()As the result of the"[object Object]", is a string, is the basic data type, and returns, end of story.

Wow ~

Is everything said to make sense, it seems not difficult 😁.

It is true that the order of execution in the JS engine is the same when using String(), except that the last basic data type is converted to a String when the result is returned.

That is to say, we have to split the third step of 👆 into two steps:

  1. {}.toString()As the result of the"[object Object]"Is a string of basic data types
  2. Will this"[object Object]"String does one more string conversion and returns. (because the"[object Object]"It is already a string, so it is returned as is, there is no difference.)

Converting the final result to a string and returning it is easy to understand. If you want to return a number or null, you can call the String method to get a String

(Cough, Lin’s real name is Wang Ha [shy ~])

9.2 the topic 2

The conversion to 👆 does not show the effect of the final conversion to a string, so let’s look at the problem:

console.log(String(null))
console.log(String(new Object(true)))
Copy the code

Think about the transformation rules here.

For the String (null) :

  • The incominginputIt’s a basic datatype, that’s easy, just return it
  • The value returned is onenullAnd convert it to a string"null", so the final return is"null".

For String(new Object(true)) :

  • The incomingnew Object(true)Is a wrapper class of basic typeBoolean{true}
  • It is also a reference type and therefore will be calledtoString()
  • The basic type of wrapper class will be covered6.8.3As already stated, it callstoString()The method is a string that returns the original value, which is"true"
  • The return value"true"Is the basic data type, and finally does one more layer of string conversion (itself), and then returns"true".

The answer:

console.log(String(null)) // "null"
console.log(String(new Object(true))) // true
Copy the code

What if you could see this? It’s starting to feel a little like that.

9.3 the title three

(Array to string)

Array to string I summarized it mainly like this:

  • An empty array[]Is converted to an empty string""
  • If the array is not empty, convert each item to a string and use it again","The connection

I’ve drawn a picture with reference type to string.

Let’s start with something simple:

console.log(String([]))
console.log(String([1]))
console.log(String([1.2]))
console.log(String(['1'.'2']))
Copy the code

The answer:

console.log(String([])) / / ""
console.log(String([1])) / / "1"
console.log(String([1.2])) / / 1, 2, ""
console.log(String(['1'.'2'])) / / 1, 2, ""
Copy the code

It’s not that difficult.

Let’s use toPrimitive’s conversion rules:

For String([1, 2]) :

  • inputAs an array[1, 2], so usetoString()The method call
  • [1, 2]Convert to string"1, 2,"The string"1, 2,"Is the original data type, and returns (I’m going to omit the other string conversion process because the return values are all strings)

9.4 the title four

Let’s add Boolean, function, NaN and see:

console.log(String([true.false]))
console.log(String([NaN.1]))

console.log(String([function () {}, 1]))
console.log(String([{ name: 'obj' }, { name: 'obj2' }]))
Copy the code

Resolution:

  • The types are all arrays, which is to convert each item of an array to a string and then use","The connection
  • The first two are fine
  • Third, the function converted to a string is its source string, i.e"function () {}"
  • Fourth, each item inside is an object and is converted to a string"[object, Object]"So there will be two of them"[object Object]"with","The connection

The answer is:

console.log(String([true.false])) // "true,false"
console.log(String([NaN.1])) // "NaN,1"

console.log(String([function () {}, 1])) // "function () {},1"
// "[object Object],[object Object]"
console.log(String([{ name: 'obj' }, { name: 'obj2' }]))
Copy the code

So when you do these kinds of problems, you generally just have to remember this rule:

  • If the array is not empty, convert each item to a string and use it again","The connection

That’s it, and then we’re going to see what each of these terms are converted to.

9.5 the topic 5

(Date type to string)

console.log(String(new Date()))
console.log(String(new Date('2020/12/09')))
Copy the code

The date-type object is converted to a date string in the local time zone, as we already saw in Question 6.8.2.

console.log(String(new Date())) // Sat Mar 28 2020 23:49:45 GMT+0800
console.log(String(new Date('2020/12/09'))) // Wed Dec 09 2020 00:00:00 GMT+0800
Copy the code

Summary – Object to string

For object to String, that is, calling String(), it is summarized as follows:

  • This method is called if the object has a toString method. If it returns a raw value, JavaScript converts the value to a string and returns the string result.
  • If the object does not have a toString method, or the method does not return a raw value, JavaScript calls the valueOf method. If the method exists, JavaScript calls it. If the return value is the original value, JavaScript converts the value to a string and returns the result of the string. (a)
  • Otherwise, JavaScript cannot get a raw value from toString or valueOf, in which case it will throw a type error exception.

This is the case with toPrimitive(object, ‘string’).

10. Convert the object to a number

If you can figure out object to string, you can figure out object to number.

We just said that the object to string case is toPrimitive(Object, ‘string’),

Then an object to a number is toPrimitive(object, ‘number’).

The difference is that toString() is called after valueOf().

Topic 10.1 a

(Basic conversion)

console.log(Number({}))
console.log(Number([]))
console.log(Number([0]))
console.log(Number([1.2]))
Copy the code

The Number ({}) :

  • We pass in an object{}, so callvalueOf()Method, the method is in the problem7.1As already mentioned, all referential type calls except the date object return itself, so the object is still returned{}
  • valueOf()The value returned is still an object, so continue callingtoString()Method, and{}calltoString()The result is a string"[object Object]"Is a basic data type
  • Now that I have the underlying data type, it’s time to return it, but I have to convert it to a number before I return it, so"[object Object]"Convert to figureNaN, so the result isNaN

The Number ([]) :

  • We pass in an array[], so callvalueOf()Method that returns itself[]
  • []Continue to calltoString()Method, while an empty array to a string is""
  • Finally, empty string""Converted to digital0return

The Number ([0]) :

  • because[0]Converting to a string is"0", and finally turning into numbers0return

For Number([1, 2]) :

  • We pass in an array[1, 2], so callvalueOf()Method returns the array itself[1, 2]
  • So go ahead and calltoString()Method, which is then converted to"1, 2,"string
  • "1, 2,"The string is finally converted to a numberNaN, so the result isNaN

Results:

console.log(Number({})) // NaN
console.log(Number([])) / / 0
console.log(Number([0])) / / 0
console.log(Number([1.2])) // NaN
Copy the code

10.2 the topic 2

(Date type to digit)

Let’s do a very special date type conversion

console.log(Number(new Date()))
Copy the code

Process analysis:

  • We pass in an object of type datenew Date(), so callvalueOf()In the title7.2Date type calls, as already stated invalueOf()Yes returns a millisecond
  • If the number of milliseconds is numeric, which is the basic data type, then the value is returned1585413652137

The answer:

console.log(Number(new Date())) / / 1585413652137
Copy the code

Summary – Object to number

So object to number, in summary, is similar to object to string:

  • If the object has a valueOf method and returns a raw value, JavaScript converts the raw value to a number and returns the number

  • Otherwise, if the object has a toString method and returns a raw value, JavaScript converts it and returns it.

  • Otherwise, JavaScript throws a type error exception.

Take a breath and take a rest after completing the 206 console.log() files for 👴…

After the language

Knowledge is priceless, support original.

Reference article:

  • Yuba – Heartache of Type Conversion in JavaScript Depth (PART 1)
  • God three -(suggested collection) native JS soul of the question, can you catch a few?
  • LINGLONG (implicit type conversion for plus)
  • “The ES5 – ToString”

You wish the world, I wish you no bugs. So much for this article.

In fact, my learning process of data type conversion is as follows:

Full of joy -> determined to understand -> frown -> solemn expression -> life without love -> small small understanding

It is true that there was a time when I had nothing to love in my life, ha, ha, ha, ha, ha, ha, ha, ha, ha. People have to be humble.

Create with your heart and live well. If you find this article helpful, give a thumbs up to 👍, thank you ~ 😁.

The guy who likes Lin Dull also hopes to follow Lin’s public account LinDaiDai or scan the following QR code 👇👇👇.

I will update some front-end knowledge content and my original article 🎉 from time to time

Your encouragement is the main motivation for my continuous creation 😊.

Related recommendations:

The most detailed BPMN.js textbook in the whole Web

If you don’t understand Babel, I’ll send you a mask.

“[Suggested stars] To come to 45 Promise interview questions a cool end (1.1W words carefully arranged)”

“[suggestion 👍] 40 more this interview questions sour cool continue (1.2W word by hand)”

“[why not three even] more simple than inheritance of JS inheritance – packaging (small test)”

【 Why not three times 】 finish these 48 questions to thoroughly understand JS inheritance (1.7W words including hot finishing – back to nature)

Data type conversion from 206 console.log()