preface

Symbol.toprimitive is a built-in abstraction operation that exists as a function value property of an object and is called when an object is converted to the corresponding original value.

Note: The concept of a primitive value is involved here, so before going into toPrimitive, what is a primitive value?

Let’s get started

The original and reference values of js

In ECMAScript, variables can hold two types of values, original values and reference values.

The original value(primitive value):

Raw values are fixed and simple values, simple segments of data stored in the stack, that is, their values are stored directly where the variables are accessed.

The latest ECMAScript standard defines seven primitive values: undefined, Boolean, Number, String, BigInt, Symbol, and NULL.

In fact, null was not a primitive type earlier this year.

Reference value(reference value):

A reference value is a large object stored in the heap. That is, the value stored on a variable is a pointer to the memory where the object is stored.

All reference types are integrated from Object.

If a value is of a reference type, its storage space is allocated from the heap. Because the size of the reference value changes, it cannot be placed on the stack, which would slow down the query. Instead, the value in the stack space where the variable is stored is the address of the object stored in the heap. The size of the address is fixed, so putting it on the stack has no negative impact on variable performance. As shown in figure:

Let’s look at MDN’s definition of a raw value:

The original value( primitive values )

All types except Object are immutable (the value itself cannot be changed). For example, unlike C, strings in JavaScript are immutable. We call these types of values “raw values.”

ToPrimitive abstract operation of js raw value conversion

Symbol.toprimitive is a built-in abstraction operation that exists as a function value property of an object and is called when an object is converted to the corresponding original value.

When this function is called, it is passed a string argument representing the expected type of the original value to be converted to. The value can be “number”, “string”, or “default”.

ToPrimitive conversion rules are as follows:

If the argument is passed in as string, the object to string conversion goes through the following steps:

  • If the object hastoString()Method is called. If it returns a raw value(undefined, Boolean, Number, String, BigInt, Symbol and null), js converts the value to a string (if it is not a string itself) and returns the string result.
  • If the object doesn’t havetoString()Method, ortoString()If no original value is returned, js will callvalueOf()Methods. If the return value is the original value, JS converts the value to a string and returns the string result.
  • Otherwise, JS throws a type error exception.

If the argument passed is number/default, which is an object-to-number conversion, the steps are as follows:

A bit different from the above, the conversion to a number first tries to use the valueOf() method

  • If the object hasvalueOf()Method, which returns a raw value, which js converts to a number (if needed) and returns the number.
  • Otherwise, if the object hastoString()Method, which returns a raw value (a string literal), js converts it to a number type and returns the number.
  • Otherwise, JS throws a type error exception.

Note: For all non-date objects, the object-to-primitive conversion is basically an object-to-number conversion

A special case of a date object

The Date object in the prototype defines toString() as date.prototype.toString ().

1 var date = new Date(a);2 date.toString(); // => "Mon Dec 28 2015 21:58:10 GMT+0800"
Copy the code

The Date Object covered the inherited from Object to Object. The prototype, the toString () method. Date’s toString() method always returns a string in The American English Date format. The toString() method is called automatically when a date object is used as a text value or for string concatenation.

“+” and “==” apply a special case of object-to-primitive conversions that contain date objects.

The date class is the only pre-defined type at the core of the JavaScript language that defines meaningful conversions to string and number types.

For all non-date objects, the conversion from an object to a raw value is basically an object-to-number conversion (valueOf() is called first), while date objects use the object-to-string conversion pattern. However, the conversion is not exactly the same as described above: Raw values returned by valueOf or toString() will be used directly and will not be cast to numbers or strings.

Like “==”, the “<” operator and other relational operators do object-to-value conversions, except for the special case of date objects: any object will first try calling valueOf() and then toString(). Whether the resulting original value is used directly or not, it is not further converted to a number or string.

“+”, “==”, “! The =” and relational operators are the only operators that perform this special string-to-raw conversion. The conversion of other operators to specific types is unambiguous, and there are no special cases for date objects. For example, the “-,, (minus) operator converts both of its operands to numbers.

Here is an example of code:

var now = new Date(); // Current time typeof (now + 1); // "string" typeof (now-1); // "number" now == now.toString (); // true now > (now-1); // trueCopy the code
>var now = new Date(a); >now +1
>'Fri Oct 01 2021 10:58:55 GMT+0800 1'
>now - 1
>1633057135763
Copy the code

String concatenation is confused with arithmetic implicit conversion rules

console.log(1 + true); //2 console.log(1 + "true"); //"1true" console.log(1 + undefined); //NaN console.log(1 + null); / / 1Copy the code

If one side of the + is a String, the + is a String concatenator, which calls the String() method from other data types into a String and then concatenates it;

+ as an arithmetic operator converts other data types called Number() into numbers and then adds;

The Boolean true is converted to the number 1,

Undefined will be converted to NaN,

Null is converted to the number 0

Example explanation

/ / hole
console.log ( [] == 0 );        //true
console.log ( ! [] = =0 );      //true
/ / god pit
console.log ( [] == ! []);//true
console.log ( [] == [] );       //false
// Epic pit
console.log({} == ! {});//false
console.log({} == {});      //false
Copy the code

[] Comparison with 0:

(1) [].valueof ().toString() returns an empty string

(2) Number(“”) == 0

! [] Comparison with 0:

(1) Logical non-priority over relational operators! [] = false

(2) False == 0

[] with! [] comparison:

(1) [].valueof ().toString() returns an empty string “”

(2)! [] = false

(3) Number(“”) == Number(false)

[] comparison with [] :

Reference type data is stored in heap memory, and stack memory stores addresses, so their result is false

{} with! {} comparison:

(1) {}.valueof ().toString() gets string ‘[object object]’

(2)! {} = false

(3) Number(‘[object object]’) == Number(false

Compare {} with {} :

Reference type data is stored in heap memory, and stack memory stores addresses, so their result is false

> > {} + []0
Copy the code

An empty object plus an empty array is different. The plus operator is defined like this: if one of them is a string, the other is also converted to a string, otherwise both operands are converted to numbers. At the same time, javascript has the property that if {} can be thought of as both a code block and an object literal, js will treat it as a code block.

This is easy to explain, {} is treated as a block of code, only +[], according to the definition of addition, is converted to zero, and you get the result.

valueOf() 和 toString()

🔸 the valueOf ()

The valueOf() method returns the original valueOf the specified object.

JavaScript calls the valueOf method to convert the object to its original value. You rarely need to call the valueOf method yourself; JavaScript automatically calls it when it encounters an object with a raw value to expect.

🔸 toString ()

The toString() method returns a string representing the object.

Each object has a toString() method, which is called automatically when the object is represented as a text value, or when an object is referenced as an expected string. By default, the toString() method is inherited by each Object.

What are the results of valueOf() and toString() for 🔸 {} and []?

Note: You can call a method in Chrome directly with parentheses (), including values

([]).valueOf()
([]).toString()
({}).valueOf()
({}).toString()
Copy the code

reference

  • JavaScript object to string, number conversion process
  • Javascript– Original and reference values — Localhost
  • (3) Data type conversion
  • JS Raw value Conversion algorithm — toPrimitive()
  • JS implicit data type conversion
  • Talk about JS ToPrimitive raw value conversion method