This is the second day of my participation in the August Challenge. For more details, see:August is more challenging

preface

If you simplify js types, you can divide them into two types: reference types and value types. Object and Function are reference types, and the rest are value types.

The body of the

From value types to reference types

You can do this with Object() or new Object()

When called as a non-constructor, Object behaves the same as new Object().

MDN is explained as follows:

  • If the given value is null or undefined, an empty object is created and returned
  • If a value of a primitive type is passed in, an object of its wrapper type is constructed
  • If a value of a reference type is passed in, the value will still be returned, and the variable copied by them will retain the same reference address as the source object

From the above, we can draw the following conclusions:

 let o = Object(1)
 // The result is true
 console.log(Object.getPrototypeOf(o) == Number.prototype)
 
 let a = {}
 o = Object(a)
 // The result is true
 console.log(Object.getPrototypeof(o) == a)
Copy the code

As you can see, the conversion from the value to the reference is relatively simple, just passing the Object to get the expected reference Object.

Reference type to value type

Converting references to values involves three functions: toString, valueOf, [Symbol. ToPrimitive]

toString

Returns a string representing the object

Automatically called when the object is represented as a text value, or when an object is referenced as a string as expected

valueOf

Returns the original value of the specified object

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

Common return values

  • Array Returns the Array object itself
  • Object itself
  • Function itself
  • String String

If the object has no original value, then valueOf returns the object itself

Symbol.toPrimitive

ToPrimitive is a built-in Symbol value that exists as a function value attribute of an object. This function is called when an object is converted to its original value.

When this function is called, it is passed a string parameter hint that indicates the expected type of the original value to be converted to. The hint argument is either “number”, “string”, or “default”

Returns raw data, (String, number, bigint, Boolean, null, undefined, symbol)

For example

const object = {
  [Symbol.toPrimitive](hint) {
    console.log('hint', hint)
    if (hint === 'number') {
      return 0;
    } else if (hint === 'string') { 
      return 'string'
    } else {
      return '1'}}};// Output hint as default
console.log(object + 2);
// Output hint as number
console.log(object - 2)
// Output hint as string
console.log(`${obj}`)};Copy the code

process

The conversion process of the variable x during the operation

  1. If x is the original value, return x directly
  2. If x is an object (Number, String, Boolean), it passesvalueOfReturn original value
  3. If the object has no original value, it needs to be cast. In JS, if an operation cannot determine the type, its operand is preset tonumber, corresponding to the hint of the toPrimitive above. When a hint isnumberIs invoked firstvalueOfMethods; Otherwise call firsttoString. Also, another method is called when the first method does not get a non-object value.

Some examples

const toString = Number.prototype.toString
const valueOf = Number.prototype.valueOf
Number.prototype.toString = function() {
    console.log('toString')
    return toString.call(this)}Number.prototype.valueOf = function() {
    console.log('valueOf')
    return valueOf.call(this)}let o = Object(Number(1))
o[Symbol.toPrimitive]= function(hint) {
    console.log('toPrimitive', hint)
}
Copy the code

When the output executes ${o}, the hint is expected to be string, so toString is preferentially executed.

/ / print the valueOf
console.log(o - 2)
/ / print the valueOf
console.log(o + 2)
/ / print the toString
console.log(`${o}`)
Copy the code

To the Object

const toString = Object.prototype.toString
const valueOf = Object.prototype.valueOf
Object.prototype.toString = function() {
    console.log('toString')
    return toString.call(this)}Object.prototype.valueOf = function() {
    console.log('valueOf')
    return valueOf.call(this)}let o = {a: 2}
Copy the code

The first two items are expected to be numbers, so valueOf is executed first, but the object is returned, so toString is executed

// Print valueOf first
// Print toString()
console.log(+o)
// Print valueOf first
// Print toString()
console.log(o - 2)
/ / print the toString ()
console.log(`${o}`)
Copy the code

If you add Symbol. ToPrimitive to the above object, you will find that valueOf and toString are no longer executed because the default Symbol. ToPrimitive calls valueOf and toString according to the hint. Nature will not call again.

o[Symbol.toPrimitive]= function(hint) {
    console.log('toPrimitive', hint)
}
Copy the code

If x == x is not true, it is not true. If x == x is not true, it is true.

reference

  • Developer.mozilla.org/zh-CN/docs/…
  • zhuanlan.zhihu.com/p/29730094
  • Time.geekbang.org/column/arti…