Data type conversion

Overview

JavaScript is a dynamically typed language. Variables have no type restrictions and can be assigned any value at any time.

var x = y ? 1 : "a";

In the above code, whether the variable x is a numeric value or a string depends on the value of another variable y. When y is true, x is a numeric value; when y is false, x is a string. This means that the type of x cannot be known at the compilation stage, and it must be known at runtime.

Although the data type of the variable is uncertain, various operators have requirements for the data type. If the operator finds that the type of the operator does not match the expectation, it will automatically convert the type. For example, the subtraction operator expects that the operators on the left and right sides should be numeric values, if not, it will automatically convert them to numeric values.

"4" - "3"; // 1

In the above code, although the two strings are subtracted, the result value 1 will still be obtained. The reason is that JavaScript automatically converts the operator to a value.

This chapter explains the rules for automatic conversion of data types. Before that, let me explain how to manually cast data types.

Mandatory conversion

Coercion mainly refers to the use of the three functions Number(), String() and Boolean() to manually convert various types of values ​​into numbers, strings or Boolean values, respectively.

Number()

Using the Number function, you can convert any type of value into a number.

The discussion is divided into two situations below, one is that the parameter is the value of the original type, and the other is that the parameter is the object.

(1) Original type value

The conversion rules for primitive type values ​​are as follows.

// Value: the original value after conversion
Number(324); // 324

// String: If it can be parsed as a numeric value, then converted to the corresponding numeric value
Number("324"); // 324

// String: If it cannot be parsed as a number, return NaN
Number("324abc"); // NaN

// Empty string is converted to 0
Number(""); // 0

// Boolean value: true turns to 1, false turns to 0
Number(true); // 1
Number(false); // 0

// undefined: converted to NaN
Number(undefined); // NaN

// null: turn to 0
Number(null); // 0

The Number function converts a string to a numeric value, which is much stricter than the parseInt function. Basically, as long as one character cannot be converted into a numeric value, the entire string will be converted to NaN.

parseInt("42 cats"); // 42
Number("42 cats"); // NaN

In the above code, parseInt parses the characters one by one, and the Number function converts the type of the string as a whole.

In addition, the parseInt and Number functions will automatically filter the leading and suffix spaces of a string.

parseInt("\t\v\r12.34\n"); // 12
Number("\t\v\r12.34\n"); // 12.34

(2) Object

The simple rule is that when the parameter of the Number method is an object, it will return NaN, unless it is an array containing a single number.

Number({ a: 1 }); // NaN
Number([1, 2, 3]); // NaN
Number([5]); // 5

This happens because the conversion rules behind Number are more complicated.

The first step is to call the object's own valueOf method. If it returns a value of the original type, use the Number function directly on the value, and no further steps are required.

In the second step, if the valueOf method returns an object, the toString method of the object itself is called instead. If the toString method returns a value of the original type, use the Number function for the value, and no further steps are required.

In the third step, if the toString method returns an object, an error will be reported.

Please see the example below.

var obj = { x: 1 };
Number(obj); // NaN

// Equivalent to
if (typeof obj.valueOf() === "object") {
  Number(obj.toString());
} else {
  Number(obj.valueOf());
}

In the above code, the Number function converts the obj object into a number. Behind the scenes a series of operations, first call the obj.valueOf method, the result returns the object itself; then, continue to call the obj.toString method, then return the string [object Object], use for this string Number function, get NaN.

By default, the valueOf method of an object returns the object itself, so the toString method is always called, and the toString method returns the type string of the object (such as [object Object]). So, there will be the following result.

Number({}); // NaN

If the value returned by the toString method is not a primitive type, the result will be an error.

var obj = {
  valueOf: function () {
    return {};
  },
  toString: function () {
    return {};
  },
};

Number(obj);
// TypeError: Cannot convert object to primitive value

The valueOf and toString methods of the above code all return objects, so an error will be reported when they are converted to numeric values.

You can also see from the above example that the valueOf and toString methods can be customized.

Number({
  valueOf: function () {
    return 2;
  },
});
// 2

Number({
  toString: function () {
    return 3;
  },
});
// 3

Number({
  valueOf: function () {
    return 2;
  },
  toString: function () {
    return 3;
  },
});
// 2

The above code uses the Number function on three objects. The first object returns the value of the valueOf method, the second object returns the value of the toString method, and the third object indicates that the valueOf method is executed before the toString method.

String()

The String function can convert any type of value into a string. The conversion rules are as follows.

(1) Original type value

-Numeric: Convert to the corresponding string. -String: The original value after conversion. -Boolean value: true is converted to the string "true", and false is converted to the string "false". -undefined: converted to a string "undefined". -null: converted to a string "null".

String(123); // "123"
String("abc"); // "abc"
String(true); // "true"
String(undefined); // "undefined"
String(null); // "null"

(2) Object

If the parameter of the String method is an object, it returns a typed string; if it is an array, it returns the string form of the array.

String({ a: 1 }); // "[object Object]"
String([1, 2, 3]); // "1,2,3"

The conversion rules behind the String method are basically the same as the Number method, except that the execution order of the valueOf method and the toString method are interchanged.

  1. First call the object's own toString method. If it returns a value of the original type, use the String function for the value and do not perform the following steps.

  2. If the toString method returns an object, then call the valueOf method of the original object. If the valueOf method returns a value of the original type, use the String function for the value and do not perform the following steps.

  3. If the valueOf method returns an object, an error will be reported.

Below is an example.

String({ a: 1 });
// "[object Object]"

// Equivalent to
String({ a: 1 }.toString());
// "[object Object]"

The above code first calls the toString method of the object, and finds that the string [object Object] is returned, so the valueOf method is no longer called.

If the toString method and the valueOf method both return objects, an error will be reported.

var obj = {
  valueOf: function () {
    return {};
  },
  toString: function () {
    return {};
  },
};

String(obj);
// TypeError: Cannot convert object to primitive value

The following is an example of changing the return value by customizing the toString method.

String({
  toString: function () {
    return 3;
  },
});
// "3"

String({
  valueOf: function () {
    return 2;
  },
});
// "[object Object]"

String({
  valueOf: function () {
    return 2;
  },
  toString: function () {
    return 3;
  },
});
// "3"

The above code uses the String function on three objects. The first object returns the value of the toString method (value 3), the second object returns the value of the toString method ([object Object]), and the third object indicates that the toString method precedes the The valueOf method is executed.

Boolean()

The Boolean() function can convert any type of value to a Boolean value.

Its conversion rules are relatively simple: Except for the conversion results of the following five values, which are false, all other values ​​are true.

-undefined -null -0 (including -0 and +0) -NaN -'' (empty string)

Boolean(undefined); // false
Boolean(null); // false
Boolean(0); // false
Boolean(NaN); // false
Boolean(""); // false

Of course, the two boolean values ​​of true and false will not change.

Boolean(true); // true
Boolean(false); // false

Note that the conversion result of all objects (including empty objects) is true, and even the Boolean object new Boolean(false) corresponding to false is also true (see "Packaging Objects of Primitive Type Values" for details. chapter).

Boolean({}); // true
Boolean([]); // true
Boolean(new Boolean(false)); // true

The boolean value of all objects is true. This is because when the JavaScript language was designed, for performance reasons, if the object needs to be calculated to get the boolean value, it may require more for scenes like obj1 && obj2 Calculation. In order to ensure performance, it is uniformly stipulated that the Boolean value of the object is true.

Automatic conversion

The following describes automatic conversion, which is based on forced conversion.

When encountering the following three situations, JavaScript will automatically convert the data type, that is, the conversion is done automatically and is not visible to the user.

In the first case, different types of data are operated on each other.

123 + "abc"; // "123abc"

In the second case, a Boolean value is evaluated for data of a non-Boolean value type.

if ("abc") {
  console.log("hello");
} // "hello"

In the third case, unary operators (ie + and -) are used for non-numeric values.

+{ foo: "bar" } - // NaN
  [1, 2, 3]; // NaN

The rule of automatic conversion is as follows: what type of value is expected, the conversion function of that type is called. For example, if a certain position is expected to be a string, call the String() function to convert it. If the position can be either a string or a numeric value, it will be converted to a numeric value by default.

Since automatic conversion is uncertain and not easy to debug, it is recommended to use Boolean(), Number() and String() functions for explicit expressions where Boolean values, numbers, and strings are expected Conversion.

Automatically convert to boolean

When JavaScript encounters a place that is expected to be a Boolean value (such as the conditional part of an if statement), it will automatically convert the non-Boolean parameter to a Boolean value. The Boolean() function is automatically called inside the system.

Therefore, except for the following five values, the others are automatically converted to true.

-undefined -null -+0 or -0 -NaN -'' (empty string)

In the following example, each value of the conditional part is equivalent to false, after using the negation operator, it becomes true.

if (!undefined && !null && !0 && !NaN && !"") {
  console.log("true");
} // true

The following two ways of writing are sometimes used to convert an expression to a Boolean value. They also call the Boolean() function internally.

// Writing method one
expression ? true : false;

// Writing method two
!!expression;

Automatically convert to string

When JavaScript encounters a place that is expected to be a string, it will automatically convert a non-string value to a string. The specific rule is to first convert the value of the composite type to the value of the original type, and then convert the value of the original type to a string.

The automatic conversion of character strings mainly occurs during the addition operation of character strings. When one value is a string and the other value is not a string, the latter is converted to a string.

"5" + 1; // '51'
"5" + true; // "5true"
"5" + false; // "5false"
"5" + {}; // "5[object Object]"
"5" + []; // "5"
"5" + function () {}; // "5function (){}"
"5" + undefined; // "5undefined"
"5" + null; // "5null"

This automatic conversion is prone to errors.

var obj = {
  width: "100",
};

obj.width + 20; // "10020"

In the above code, the developer may expect to return 120, but due to automatic conversion, a character 10020 is actually returned.

Automatically convert to numeric value

When JavaScript encounters a place that is expected to be a numeric value, it will automatically convert the parameter value to a numeric value. The Number() function is automatically called inside the system.

Except for the addition operator (+), which may convert operators into strings, other operators will automatically convert operators into numeric values.

"5" - "2"; // 3
"5" * "2"; // 10
true - 1; // 0
false - 1; // -1
"1" - 1; // 0
"5" * []; // 0
false / "5"; // 0
"abc" - 1; // NaN
null + 1; // 1
undefined + 1; // NaN

In the above code, the operators on both sides of the operator are all converted to numeric values.

Note: When null is converted to a number, it is 0, and when undefined is converted to a number, it is NaN.

Unary operators also convert operators into numbers.

+"abc" - // NaN
  "abc" + // NaN
  true - // 1
  false; // 0