One part of JavaScript that is complex, error-prone, controversial, and widely used is type conversions.

preface

Converting a value from one type to another is often called type conversion.

Before ES6, JavaScript has six data types: Undefined, Null, Boolean, Number, String, and Object.

Let’s start by looking at conversions between primitive types.

The original value goes to Boolean

We use the Boolean function to convert a type to a Boolean type. In JavaScript, only six values can be converted to false; all others are converted to true.

console.log(Boolean()) // false

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

console.log(Boolean(undefined)) // false
console.log(Boolean(null)) // false
console.log(Boolean(+0)) // false
console.log(Boolean(0)) // false
console.log(Boolean(NaN)) // false
console.log(Boolean("")) // false
Copy the code

Note that the Boolean function returns false when it passes no arguments.

Convert the original value to a number

We can use the Number function to convert the type to a Number, and return NaN if the parameter cannot be converted to a Number.

Before looking at examples, let’s look at the ES5 specification 15.7.1.1 for Number:

According to the specification, the Number function returns +0 if it takes no arguments, and ToNumber(value) is called if it has arguments.

Note that this ToNumber represents a method on the underlying specification implementation and is not directly exposed.

ToNumber gives a table of corresponding results. Table is as follows:

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 This is a bit more complicated. Let’s do an example

Let’s write some examples to verify this:

console.log(Number()) / / + 0

console.log(Number(undefined)) // NaN
console.log(Number(null)) / / + 0

console.log(Number(false)) / / + 0
console.log(Number(true)) / / 1

console.log(Number("123")) / / 123
console.log(Number("123")) / / - 123
console.log(Number("1.2")) / / 1.2
console.log(Number("000123")) / / 123
console.log(Number("000123")) / / - 123

console.log(Number("0x11")) / / 17

console.log(Number("")) / / 0
console.log(Number("")) / / 0

console.log(Number("123, 123")) // NaN
console.log(Number("foo")) // NaN
console.log(Number("100a")) // NaN
Copy the code

If you pass a string through the Number conversion function, it tries to convert it to an integer or floating point Number, ignores all leading zeros, and returns NaN if any character is not a Number. Given this strict judgment, We also typically use the more flexible parseInt and parseFloat for conversions.

ParseInt parses only integers. ParseFloat parses both integers and floating-point numbers. If a string is prefixed with “0x” or “0x”, parseInt interprets it as a hexadecimal number. Parse as many numeric characters as possible and ignore the rest. NaN is eventually returned if the first non-space character is an illegal numeric direct quantity:

console.log(parseInt("3 abc")) / / 3
console.log(parseFloat("3.14" ABC "")) / / 3
console.log(parseInt("12.34")) / / - 12
console.log(parseInt("0xFF")) / / 255
console.log(parseFloat("1")) / / 0.1
console.log(parseInt("0.1")) / / 0
Copy the code

Original value transpose character

We use the String function to convert a type to a String. Let’s look at the String function in 15.5.1.1:

If String takes no arguments, it returns an empty String. If it has arguments, ToString(value) is called, and ToString gives a corresponding result table. Table is as follows:

The parameter types The results of
Undefined “undefined”
Null “null”
Boolean Return “true” if the argument is true. Parameter false, return “false”
Number Again, it’s a little bit more complicated, so let’s look at an example
String Returns the value equal to it

Let’s write some examples to verify this:

console.log(String()) // An empty string

console.log(String(undefined)) // undefined
console.log(String(null)) // null

console.log(String(false)) // false
console.log(String(true)) // true

console.log(String(0)) / / 0
console.log(String(0)) / / 0
console.log(String(NaN)) // NaN
console.log(String(Infinity)) // Infinity
console.log(String(-Infinity)) // -Infinity
console.log(String(1)) / / 1
Copy the code

Note that both ToString here and ToNumber in the previous section are methods implemented by the underlying specification and are not directly exposed.

The original value goes to the object

The conversion of primitive values to objects is simple, with primitive values being converted to their respective wrapper objects by calling String(), Number(), or Boolean() constructors.

Null and undefined are exceptions, and when used where an object is expected, both raise a TypeError exception and do not perform normal conversions.

var a = 1;
console.log(typeof a); // number
var b = new Number(a);
console.log(typeof b); // object
Copy the code

Object to Boolean value

The object-to-boolean conversion is simple: all objects (including arrays and functions) are converted to true. The same is true for wrapping objects, for example:

console.log(Boolean(new Boolean(false))) // true
Copy the code

Object to string and number

Both object-to-string and object-to-number conversions are done by calling a method on the object to be converted. JavaScript objects have two different methods to perform the conversion, toString and valueOf. Note that this is different from the ToString and ToNumber methods mentioned above, which are the real exposed methods.

All objects have a toString method for any value other than null and undefined. In general, this method returns the same result as the String method. The toString method returns a string that reflects the object, but that’s where the complications begin.

In the JavaScript project (on) the types of judgment when it comes to an Object in 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. Here’s an example:

Object.prototype.toString.call({a: 1}) // "[object Object]"
({a: 1}).toString() // "[object Object]"
({a: 1}).toString === Object.prototype.toString // true
Copy the code

We can see that when we call the toString method of an Object, we actually call the toString method of Object.prototype.

However, many classes in JavaScript define more versions of toString methods, depending on their characteristics. Such as:

  1. The toString method of an array converts each array element to a string, which is combined into a result string by adding commas between the elements.
  2. The toString method of the function returns the source code string.
  3. The toString method of a date returns a readable date and time string.
  4. RegExp’s toString method returns a string representing the regular expression’s immediate quantity.

Reading text too abstract? Let’s just write the example:

console.log(({}).toString()) // [object Object]

console.log([].toString()) / / ""
console.log([0].toString()) / / 0
console.log([1.2.3].toString()) / / 1, 2, 3
console.log((function(){var a = 1; }).toString())// function (){var a = 1; }
console.log((/\d+/g).toString()) // /\d+/g
console.log((new Date(2010.0.1)).toString()) // Fri Jan 01 2010 00:00:00 GMT+0800 (CST)
Copy the code

Another function that converts an object is valueOf, which represents the original valueOf the object. The default valueOf method returns the object itself, and arrays, functions, and regees simply inherit the default method and return the object itself. The exception is the date, which returns one of its content representations: the number of milliseconds since January 1, 1970.

var date = new Date(2017.4.21);
console.log(date.valueOf()) / / 1495296000000
Copy the code

The object then converts to strings and numbers

With the toString and valueOf methods in mind, let’s look at how objects are converted to strings. ES5 9.8 is the equivalent of ToString, but this time we add the Object conversion rule:

The parameter types The results of
Object 1. primValue = ToPrimitive(input, String)

2. Return the ToString (primValue).

The so-called ToPrimitive method simply takes a value and returns a value that must be of a primitive type.

To summarize, when we use String to convert a value to a primitive type, we refer to the table in the section on “Primitive value to character”. If it is not a primitive type, we call a ToPrimitive method to convert it to a primitive type. Then refer to the corresponding table in the section “Raw value to character” for conversion.

The same is true for converting objects to numbers:

The parameter types The results of
Object 1. primValue = ToPrimitive(input, Number)

2. Return ToNumber(primValue).

The ToPrimitive method is used for all conversions to base values, but the final processing is different depending on the argument, with ToString being called for converting ToString and ToNumber being called for converting ToNumber.

ToPrimitive

The next step is to take a look at ToPrimitive, which is easy once you know the toString and valueOf methods.

Let’s look at specification 9.1, where the function syntax looks like this:

ToPrimitive(input[, PreferredType])
Copy the code

The first parameter, input, represents the input value to be processed.

The second parameter is the PreferredType, which is optional and indicates the type you want to convert to. You can choose from two values, Number or String.

When the PreferredType is not passed, it is equivalent to a String if the input is of date type, and a Number otherwise.

If the input is Undefined, Null, Boolean, Number, or String, the value is returned.

If ToPrimitive(obj, Number) is used, the procedure is as follows:

  1. If obj is a basic type, return it directly
  2. Otherwise, the valueOf method is called, and if a raw value is returned, JavaScript returns it.
  3. Otherwise, the toString method is called, and if a raw value is returned, JavaScript returns it.
  4. Otherwise, JavaScript throws a type error exception.

If it is ToPrimitive(obj, String), the processing is as follows:

  1. If obj is a basic type, return it directly
  2. Otherwise, the toString method is called, and if a raw value is returned, JavaScript returns it.
  3. Otherwise, the valueOf method is called, and if a raw value is returned, JavaScript returns it.
  4. Otherwise, JavaScript throws a type error exception.

Object to string

So in summary, object to string (the Number() function) can be summarized as:

  1. 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.
  2. 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.
  3. Otherwise, JavaScript cannot get a raw value from toString or valueOf, in which case it will throw a type error exception.

Object to number

JavaScript does the same thing when you convert an object to a number, except that it tries the valueOf method first

  1. If the object has a valueOf method and returns a raw value, JavaScript converts the raw value to a number and returns the number
  2. Otherwise, if the object has a toString method and returns a raw value, JavaScript converts it and returns it.
  3. Otherwise, JavaScript throws a type error exception.

Here’s an example:

console.log(Number({})) // NaN
console.log(Number({a : 1})) // NaN

console.log(Number([])) / / 0
console.log(Number([0])) / / 0
console.log(Number([1.2.3])) // NaN
console.log(Number(function(){var a = 1; }))// NaN
console.log(Number(/\d+/g)) // NaN
console.log(Number(new Date(2010.0.1))) / / 1262275200000
console.log(Number(new Error('a'))) // NaN
Copy the code

Notice that in this example, [] and [0] both return 0, while [1, 2, 3] returns a NaN. Let’s analyze the reasons:

When Number([]) is called, valueOf of [] returns []. ToString returns an empty string because it returns an object, and ToNumber returns ToNumber. According to the corresponding table, the conversion is 0, so the final result is 0.

When Number([1, 2,3]) is called, valueOf ([1, 2,3]) is called, then toString (1,2,3) is called, then ToNumber is called, referring to the corresponding table. Because it cannot be converted to a number, the final result is NaN.

JSON.stringify

It’s worth noting that the json.stringify () method converts a JavaScript value to a JSON string and also calls the toString method, which is also a type conversion method. Json.stringify: Json.stringify:

1. Handle primitive types in much the same way as toString, except for undefined

console.log(JSON.stringify(null)) // null
console.log(JSON.stringify(undefined)) // undefined, note that undefined is not undefined in a string
console.log(JSON.stringify(true)) // true
console.log(JSON.stringify(42)) / / 42
console.log(JSON.stringify("42")) 42 "/ /"
Copy the code

2. Booleans, numbers, and strings are automatically converted to their original values during serialization.

JSON.stringify([new Number(1), new String("false"), new Boolean(false)]); // "[1,"false",false]"
Copy the code

3. Undefined, arbitrary functions, and symbol values are ignored during serialization (when they appear in property values of non-array objects) or converted to NULL (when they appear in arrays).

JSON.stringify({x: undefined.y: Object.z: Symbol("")}); 
/ / "{}"

JSON.stringify([undefined.Object.Symbol("")]);          
// "[null,null,null]" 
Copy the code

4. Json.stringify takes a second argument, replacer, which can be an array or a function that specifies which properties should be processed and which should be excluded during object serialization.

function replacer(key, value) {
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

var foo = {foundation: "Mozilla".model: "box".week: 45.transport: "car".month: 7};
var jsonString = JSON.stringify(foo, replacer);

console.log(jsonString)
// {"week":45,"month":7}
Copy the code
var foo = {foundation: "Mozilla".model: "box".week: 45.transport: "car".month: 7};
console.log(JSON.stringify(foo, ['week'.'month']));
// {"week":45,"month":7}
Copy the code

5. If a serialized object has a toJSON method, the toJSON method overrides the default serialization behavior of the object: instead of the object being serialized, the return value of the call to toJSON is serialized, for example:

var obj = {
  foo: 'foo'.toJSON: function () {
    return 'bar'; }};JSON.stringify(obj);      // '"bar"'
JSON.stringify({x: obj}); // '{"x":"bar"}'
Copy the code

In-depth series

JavaScript In-depth series directory address: github.com/mqyqingfeng…

This in-depth JavaScript series is designed to help you understand the basics of JavaScript, including prototypes, scopes, execution contexts, variable objects, this, closures, passing by value, call, apply, bind, new, and inheritance.

If there is any mistake or not precise place, please be sure to give correction, thank you very much. If you like or are inspired by it, welcome star and encourage the author.

And then the other

Established a “front-end school recruitment interview sprint mutual aid group”, welcome to add “Taoxiaozhao233” into the group ~