ValueOf and toString are methods of Object.prototype. These methods are rarely called directly, but they are called when an operation is performed using an object. I think most people have the following questions:

  • Which has a higher priority, valueOf or toString?
  • Whether valueOf and toString are called in all scenarios

Concept to explain

  • ValueOf: Returns the original value representation of an object
  • ToString: Returns a string representation of an object

Take a look at the transformation rules before introducing the following, which are based on the rule table:

ValueOf Conversion rule

ValueOf is the Object. Prototype method. All objects derived from Object have this method, but many built-in objects override this method to fit their needs.

When it comes to primitive values, we must refer to primitive types. In the JS specification, primitive types are as follows:

  • Boolean
  • Null
  • Undefined
  • Number
  • String

The rules for rewriting non-primitive values (that is, objects) are as follows:

object The valueOf the return value
Array The array itself
Boolean Boolean value
Date Returns a timestamp in milliseconds
Function The function itself
Number A numeric value
Object The object itself
String A string value

The following rules are validated, so if you are not interested in the validation process, you can just look at the transformation rules.

It is recommended to look at the validation process for further understanding

Object to a Boolean value

  1. Directly converts to true (wrapper type as well) without calling valueOf and toString

Objects are converted to numbers

When an object is expected to be used as a number, such as participating in arithmetic operations, the valueOf and toString methods are called in turn, as follows:

  1. If the object hasvalueOfMethod and returns a raw value (string, number, Boolean, undefined, null), which is converted to a number (NaN is returned on failure) and the number is returned
  2. If the object hastoStringMethod and returns a raw value (string, number, Boolean, undefined, null), which is converted to a number (NaN is returned on failure) and the number is returned
  3. TypeError is raised when conversion fails

Object to a string

  1. If the object hastoStringMethod and returns the original value (string, number, Boolean, undefined, null), the original value is converted to a string and the string is returned
  2. If the object hasvalueOfMethod and returns the original value (string, number, Boolean, undefined, null), the original value is converted to a string and the string is returned
  3. TypeError is raised when conversion fails

ToString conversion rules

object The toString return value
Array Comma-separated strings such as [1,2] toString return “1,2”
Boolean “True”
Date A readable time string, for example, “Tue Oct 15 2019 12:20:56 GMT+0800”
Function The JS source code string that declares the function
Number “Numeric value”
Object “[object Object]”
String “String”

Validates the conversion of an object to its original value

ValueOf and toString don’t have much to say and are rarely called directly in daily development, but when we use objects as raw values, conversion occurs, and the conversion process is a little confusing.

Object is converted to Boolean

In order to visually see the conversion process inside JS, I rewrote valueOf and toString, and added logs.

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function () {
    console.log('valueOf');
    return valueOf.call(this);
};
// Add toString log
Object.prototype.toString = function () {
    console.log('toString');
    return toString.call(this);
};
var a = {};
var b = new Boolean(false);

if (a) {
    console.log(1);
}
if(b) {
    console.log(2);
}
Copy the code

The output of the above example is as follows:

1
2
Copy the code

ValueOf and toString are not called, complying with the object-to-Boolean conversion rule

Object is converted to Number

Example 1

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function() {
    console.log('valueOf');
    return valueOf.call(this);
};
// Add toString log
Object.prototype.toString = function() {
    console.log('toString');
    return toString.call(this);
};
var a = {};
console.log(++a);
Copy the code

The output is as follows:

valueOf
toString
NaN
Copy the code

Analysis of the

  1. The valueOf method returns the object itself, not the original value. Continue
  2. The toString method returns “[Object object]”, which is the raw value (string), converting the string to a NaN

Example 2

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function () {
    console.log('valueOf');
    return "1"; // Force to return the original value
};
// Add toString log
Object.prototype.toString = function () {
    console.log('toString');
    return toString.call(this);
};
var a = {};
console.log(++a);
Copy the code

The output is as follows:

valueOf
2
Copy the code

Analysis of the

  1. ValueOf returns the raw value (string), which is converted directly to a number, resulting in 1

Object to a string

Conversion occurs when an object is expected to be used as a string, such as when a string concatenates strings and an object is passed in.

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function () {
    console.log('valueOf');
    return valueOf.call(this);
};
// Add toString log
Object.prototype.toString = function () {
    console.log('toString');
    return toString.call(this);
};
var a = {};
alert(a);
Copy the code

The output is as follows:

ToString // popup [object object]Copy the code

Analysis of the

  1. The toString method is called, which returns the string “[object object]” to which the object is eventually converted

Example 2

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function () {
    console.log('valueOf');
    return valueOf.call(this);
};
// Add toString log
Object.prototype.toString = function () {
    console.log('toString');
    return this;
};
var a = {};
alert(a);
Copy the code

The output is as follows:

toString
valueOf
Uncaught TypeError: Cannot convert object to primitive value
    at 1.js:16
Copy the code

Analysis of the

  1. Call toString, return no original value, continue execution
  2. Calls the valueOf method, returns no original value, and continues
  3. Throw a TypeError

Use the plus operator to concatenate strings and objects

When testing the object-to-string conversion, the following code does not behave as expected:

// Save the original valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;

// Add valueOf logs
Object.prototype.valueOf = function () {
    console.log('valueOf');
    return valueOf.call(this);
};
// Add toString log
Object.prototype.toString = function () {
    console.log('toString');
    return toString.call(this);
};

console.log("a" + {});
Copy the code

The output is as follows:

valueOf
toString
a[object Object]
Copy the code

doubt

“A “+ {} should be expected to be used as a string and toString should be called first, but this is not the case.

conclusion

The conclusions are as follows:

  1. If one of them is an object, the conversion process is followed (toString is called directly for Date objects to complete the conversion, valueOf is used for other objects, and toString is called if the conversion is unsuccessful).
  2. If both are objects, both objects follow step 1 to convert to a string
  3. Two numbers, arithmetic
  4. Two strings, directly concatenated
  5. A string a number, directly concatenated into a string

The interview questions

var a = {};
var b = {};
var c = {};
c[a] = 1;
c[b] = 2;

console.log(c[a]);
console.log(c[b]);
Copy the code

Answer key

Since the key of the object is a string, a and B in C [a] and C [b] perform the object-to-string conversion.

According to the conversion rules, both a and B are converted to object object, so c[a] and C [b] operate on the same key.

The answer is to print two 2’s. The final structure of the C object looks like this:

{
  '[object Object]':2
}
Copy the code