Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand toString and valueOf

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to understand toString and valueOf". In daily operation, I believe many people have doubts about how to understand toString and valueOf. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "how to understand toString and valueOf"! Next, please follow the editor to study!

Basically, all JS data types have these two methods, except null. These two methods are located on the prototype chain, and they are also used to solve the problem of javascript value operation and display.

Almost all valueOf and toString appear the operators (+-* / = = > {}) / [object Function] toString.call ({}) / / [object Object] toString.call ([]) / / [object Array] toString.call ('') / / [object String] toString.call (22) / / [object Number] toString.call (undefined) / / [object undefined] toString.call (null) / / [object null] toString.call (new Date) / / [object Date] toString.call (Math) / / [object Math] toString.call (window) / / [object Window]

3. When will it be called automatically?

When using an operator, if one side of the operator is an object, the toSting method is called first, that is, an implicit conversion, and then the operation is performed.

Let c = [1,2,3] let d = {console.log 2} Object.prototype.toString = function () {console.log ('Object')} Array.prototype.toString = function () {console.log (' Array') return this.join (' ') / / returns the default value of toString (the following test)} Number.prototype.toString = function () {console.log (' Number')} String.prototype.toString = function () {console.log ('String')} console.log (2 + 1) / / 3 console.log (' s') / /'s' console.log ('s') / /'s 2' console.log (c

< 2) // false (一次 =>

'Array') console.log (c + c) / / "1 Array' 2, 31 Array' 3" (twice) console.log (d > d) / / false (twice = >' Object')

4. Override the toString method

Now that we know that there is a default method of toString, we can also override this method

Class A {constructor (count) {this.count = count} toString () {return'I have so much money:'+ this.count}} let a = new A (100) console.log (a) / A {count: 100} console.log (a.toString ()) / / I have so much money: 100console.log (a +) 1) / / I have so much money: 1001

Nice.

ValueOf

Returns the original value of the current object.

The specific function is more or less the same as toString, and it also has the above automatic calling and rewriting methods.

There is nothing to say here, mainly for the difference between the two. Please continue to read on.

Let c = [1,2,3] let d = {console.log 2} console.log (c.valueOf ()) / / [1,2,3] console.log (d.valueOf ()) / / {abure2}

The difference between the two

What they have in common: it is called automatically when the object is output.

Difference: the default return value is different, and there is a priority relationship.

In the case of the coexistence of the two, in the numerical operation, valueOf is called first, and in the string operation, toString is called first.

Look at the code to know:

Class A {valueOf () {return 2} toString () {return ''} let a = new A () console.log (String (a)) / / '' = > (toString) console.log (Number (a)) / / 2 = > (valueOf) console.log (a + '22') / /' 222' = > (valueOf) console.log (a = = 2) / / true = > (valueOf) console.log (a = 2) / / false = > (strictly equals that implicit conversion will not be triggered)

The result gives the impression that the toString method is called if it is converted to a string, and the valueOf method is called if it is converted to a numeric value.

But a + '22' is very discordant, and string merging should be a call to the toString method. In order to find out the truth, we need more rigorous experiments.

Remove the valueOf method for the time being

Class A {toString () {return'ha'}} let a = new A () console.log (String (a)) / /'ha ha'= > (toString) console.log (Number (a)) / / NaN = > (toString) console.log (a + '22') / /' ha ha 22'= > (toString) console.log (a = 2) / false = > (toString)

Get rid of the toString method and see

Class A {valueOf () {return 2}} let a = new A () console.log (String (a)) / /'[object Object]'= > (toString) console.log (Number (a)) / / 2 = > (valueOf) console.log (a + '22') / /' 222'= > (valueOf) console.log (a = = 2) / / true = > (valueOf)

Notice something different?! It is not as uniform and organized as the toString above. As for that [object Object], I guess I inherited it from Object. Let's take a look at it again.

Class A {valueOf () {return 2}} let a = new A () Object.prototype.toString = null; console.log (String (a)) / / 2 = > (valueOf) console.log (Number (a)) / / 2 = > (valueOf) console.log (a + '22') / /' 222'= > (valueOf) console.log (a = 2) / / true = > (valueOf)

Summary: valueOf is biased towards operation and toString is biased towards display.

During the object conversion, the toString method is called first, if the toString is not overridden, the valueOf method is called; if neither method is overridden, press the toString output of the Object.

When making a strong conversion to a string type, the toString method is called first, and when it is converted to a number, valueOf is called first.

In the case of operational operators, valueOf takes precedence over toString.

[Symbol.toPrimitive]

MDN:Symbol.toPrimitive is a built-in Symbol value that exists as a function value property of an object, and this function is called when an object is converted to the corresponding original value.

Are you a little confused? Just think of it as a function.

Function: same as valueOf () and toString (), but with higher priority than both

When the function is called, a string argument is passed

Hint

Which represents the current mode of operation, there are three modes

String: string type

Number: numeric type

Default: default

Let's look at the implementation:

Class A {constructor (count) {this.count = count} valueOf () {return 2} toString () {return ''} / / here I am [Symbol.toPrimitive] (hint) {if (hint = = "number") {return 10 } if (hint = = "string") {return "Hello Libai";} return true }} const a = new A (10) console.log (`${a}`) / / 'Hello Libai' = > (hint = = "string") console.log (String (a)) / /' Hello Libai' = > (hint = = "string") console.log (+ a) / / 10 = > (hint = = "number") console.log (a * 20) / / 200 = > ( Hint = = "number") console.log (a / 20) / / 0.5 = > (hint = = "number") console.log (Number (a)) / / 10 = > (hint = = "number") console.log (a + '22') / /' true22' = > (hint = = "default") console.log (a = = 10) / / false = > (hint = "default")

What's special is the (+) splicer, which belongs to the default pattern.

Highlight: this method is not compatible with IE, which is so embarrassing that I don't want to write it.

Analysis of interview questions

The following interview questions that must be tested by big companies perfectly show the role of toString and valueOf.

1. A===1&&a===2&&a===3 is true

Double equal sign (= =): implicit type conversion is triggered, so you can use valueOf or toString to do so.

Each judgment will trigger the valueOf method, and let value+1 at the same time, to make the next judgment valid.

Class A {constructor (value) {this.value = value;} valueOf () {return this.value++;}} const a = new A (1); if (a = = 1 & & a = = 2 & & a = 3) {console.log ("Hi Libai!");}

Congruent (= =): strictly equal to no implicit conversion, which is implemented using Object.defineProperty data hijacking

Let value = 1; Object.defineProperty (window, 'asides, {get () {return value++}}) if (a = 1 & & a = 2 & & a = = 3) {console.log ("Hi Libai!")}

Above, we hijack the an above the global window. Every time a makes a judgment, it will trigger the get attribute to obtain the value, and each time it gets the value, it will trigger a function to implement a self-increment, and the judgment will increase itself three times, so it will finally make the formula valid.

two。 Implement an infinite accumulation function

Problem: implement an infinitely cumulative function add with JS. The example is as follows:

Add (1); / / 1 add (1) (2); / / 3 add (1) (2) (3); / / 6 add (1) (2) (3) (4); / / 10 / / and so on function add (a) {function sum (b) {/ / use closure a = b? A + b: a; / accumulate return sum;} sum.toString = function () {/ / only call return a;} return sum for the last time / / return a function} add (1) / / 1 add (1) (2) / / 3 add (1) (2) (3) / / 6 add (1) (2) (3) (4) / 10

The sum function is defined inside the add function and returned to realize continuous call.

The sum function forms a closure, accumulating values for each call, and then returning the current function sum

Add () returns a function sum every time until the last one is not called, and the toString method is triggered by default, so we rewrite the toString method here and return the cumulative final value a

This is the only way to understand:

Add (10): executes the function add (10) and returns the sum function. Note that sum is not called this time, and the sum.toString method is executed by default. So output 10

Add (10) (20): executes the function add (10), returns sum (where an is 10), then executes sum (20), where an is 30, returns sum, and finally calls sum.toString () to output 30. Add (10) (20)... (n) and so on.

3. Corialization to realize multi-parameter accumulation

Here is the cumulative upgrade above to achieve multi-parameter transfer accumulation.

Add (1) (3jue 4) (3Mague 5) / / 16 add (2) (3 Magi 5) / / 12 function add () {/ / 1 convert all parameters to an array let args = Array.prototype.slice.call (arguments) / / 2 call the add function again Pass and merge the current and previous parameters let fn = function () {let arg_fn = Array.prototype.slice.call (arguments) return add.apply (null, args.concat (arg_fn))} / / 3 last default call Returns the merged value fn.toString = function () {return args.reduce (function (a, b) {return a + b})} return fn} / / ES6 written function add () {let args = [... arguments] Let fn = function () {return add.apply (null, args.concat ([... arguments]))} fn.toString = () = > args.reduce ((a, b) = > a + b) return fn;} at this point, the study on "how to understand toString and valueOf" is over. I hope I can solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report