Full analysis of JS addition operation

Full analysis of JS addition operation

Xia Zhi pays more attention to

0.0592018.08.14 21:22:11 Word Count 2,554 Read 3,879

The ultimate proposition:
In JS: what are the results of []+[], []+{}, {}+[], {}+{}?

1. Types in JS

  • Basic types
    The basic types of JS include Undefined, Null, Boolean, Number and String. Both the Undefined type and the Null type have only one value, namely undefined and null; the Boolean type has two values: true and false; the Number type has many, many values; and the String type has theoretically countless values.
  • Value types
    in JS include primitive types (Primitive) and object types (Object). When performing operations such as addition, those that are not of primitive type must be converted to primitive types before performing related operations.

2. Addition operation in JS

1. Use the ToPrimitive operation to convert the left and right operands into primitive data types (primitive).
2. After conversion, if the original data type of one of the operands is a "string" value, the other operand will be forced to be converted to a string, and then the string concatenation operation will be performed.
3. In other cases, all operands will be converted into "number" type values ​​of the original data type, and then the numbers will be added.

3. ToPrimitive internal operation

The plus operator can only be used for primitive data types. For values ​​of object types, data conversion is required. In ECMAScript, there is an abstract ToPrimitive operation, which is used to convert objects into primitive data types. It is used in addition, relational comparison, or value equality comparison operations of objects.

Description syntax for ToPrimitive:

ToPrimitive(input, PreferredType?)

Input represents the substituted value. PreferredType can be either a number (Number) or a string (String), indicating the original type that needs to be converted first. But if this value is not provided, which is the default situation, the converted hint value will be set to "default". This preferred instruction (hint value) for converting the original type is automatically added by JS when doing internal conversion. Generally, it is the default value.

In the design of JS's Object prototype, there are two methods, valueOf and toString. During the object's data type conversion process, the order in which they are called will be adjusted according to the incoming value.

  • When PreferredType is Number (Number)
    When PreferredType is Number (Number), input is the value to be converted. Steps to convert the input value:
    1. If input is the original data type, return input directly.
    2. Otherwise, input is an object, call the valueOf() method, and if the value of the original data type can be obtained, return this value.
    3. Otherwise, input is an object, call the toString() method, and if the value of the original data type can be obtained, return this value.
    4. Otherwise, a TypeError is thrown.

  • When PreferredType is String (String)
    1. If input is a primitive data type, return input directly.
    2. Otherwise, input is an object, call the toString() method, and if the value of the original data type can be obtained, return this value.
    3. Otherwise, input is an object, call the valueOf() method, and if the value of the original data type can be obtained, return this value.
    4. Otherwise, a TypeError is thrown.

  • When PreferredType is not provided (default),
    the default type of PreferredType is Number, so valueOf() is called first, and then toString() is called.

The more special ones are Date objects and Symbol objects, which override the original PreferredType behavior. The default preferred type of Date objects is String.

4. valueOf() and toString()

valueOf() and toString() are two methods on Object, but in JS, the return values ​​may be different depending on the differences between Objects.

  • Ordinary Object object
    valueOf(): returns the object itself.
    toString(): "[object Object]" string value, the return value of different built-in objects is "[object type]" string, "type" refers to the type identification of the object itself, for example, the Math object returns " [object Math]"String. However, some built-in objects do not have this value when called directly because they override this method. (Note: The English word "object" in the front of this return string is lowercase, and the English word "object" in the back is uppercase).

Use toString in Object to judge various objects syntax:

Object.prototype.toString.call([])
"[object Array]"

Object.prototype.toString.call(new Date)
"[object Date]"

You need to cooperate with call to get the correct object type value.

  • Array (array)
    Although Array (array) is an object type, it is designed differently from Object. Its toString has coverage. Let’s explain the return values ​​of the two methods of valueOf and toString of the array: valueOf(): returns the
    object  itself
    toString ():  Equivalent to the string returned by calling join(',') with an array value. That is, [1,2,3].toString() will be "1,2,3", please pay special attention to this point.

  • Function object
    Function object is rarely used, and its toString has also been overwritten, so it is not the toString in Object, but the return value of the two methods of valueOf and toString of the Function object: valueOf():
    returns  the object itself
    toString() :  The code contained in the return function is converted into a string value.

  • Date object
    valueOf():  Returns the given time converted to UNIX time (since 1 January 1970 00:00:00 UTC), but a numeric value in microseconds
    toString():  Returns a localized time string

5. Number, String, Boolean packaging objects

JS packaging objects must use the new keyword for object instantiation, and directly use the three cast functions Number(), String() and Boolean(). For example, new Number(123), and Number('123') is a function that forces other types to be converted to numeric types.

  • Packaging object
    Packaging object is an object specially designed by JS for primitive data types such as numbers, strings, and Boolean. The two methods of valueOf and toString of the packaging object are overridden on the prototype, so their return values ​​are different from the general Object design. :
    valueOf method return value:  corresponding original data type value
    toString method return value:  corresponding original data type value, the string value
    toString method when converted to string type will be more special, the details of toString in these three packaging objects The description is as follows:
    1. The toString method of the Number packaging object: There can be a parameter passed, which can determine the carry when converting to a string (2/8/16) 2. The
    toString method of the String packaging object: It is the same as the valueOf in the String packaging object Same return result
    3. toString method of Boolean packaging object: returns "true" or "false" string

  • The three forced conversion
    functions of Number(), String() and Boolean() correspond to the comparison table of the three internal operation conversions of ToNumber, ToString and ToBoolean in the ECMAScript standard.

    Convert the value to Number through ToNumber():

    parameter result
    undefined NaN
    null +0
    boolean true is converted to 1, false is converted to +0
    number No conversion required
    string Parsed from string to number. For example, "324" is converted to 324

    Convert the value into a string using ToString():

    parameter result
    undefined “undefined”
    null “null”
    boolean "true" or "false"
    number Numbers as strings. For example, "1.765"
    string No conversion required

6. Understand from examples

  • One of the operands is a string (String)
/**
 * 运算元其一为字符串(String)
 */
console.log('12'+1);            // 121
console.log('abc'+'def');       // abcdef
console.log('1'+true);          //1true
console.log('1'+undefined);     //1undefined
console.log('1'+null);          //1null

One of the operands is a string, which is the concatenation operation of strings.

  • One of the operands is a number (Number)
/**
 * 运算元其一为数字(Number)
 */
console.log(1+1);            // 2
console.log(1+'def');       // 1def
console.log(1+true);          //2
console.log(1+undefined);     //NaN
console.log(1+null);          //1

1+'def' means that one of the operands is a string, and the rest means that if there is no string, one of the operands is a number, and they are added after type conversion.

  • Addition of primitive types other than Number/String
/**
 * 数字(Number)/字符串(String)以外的原始类型相加
 */
console.log(true+true);             // 2
console.log(true+null);             // 1
console.log(true+undefined);        //NaN
console.log(undefined+null);        //NaN
console.log(undefined+undefined);   //NaN
console.log(null+null);            //0

When other primitive data types other than numbers and strings directly use the addition operation, they are converted to numbers and then operated, which has nothing to do with strings.

  • empty array + empty array
console.log([] + []);        //""

To add two arrays, the left and right operands first call valueOf(), which returns the array itself, and then call toString(), which returns the original data type, that is, an empty string, and performs a concatenation operation to obtain an empty string.

  • empty object + empty object
console.log({} + {});        //"[object Object][object Object]"

To add two objects, the left and right operands first call valueOf(), return the object itself, call toString(), return the original data type, that is, the object string [object Object], perform a connection operation, and obtain the string [object Object][ object Object]

Console.log({}+{}) gets this result. However, if you directly enter {}+{} in some browsers such as Firefox and Edge console, you will get NaN, because the browser will treat {} + {} The literal translation is equivalent to the +{} statement, because they will think that the curly bracket ({) starts with the beginning of a block statement, not an object literal, so they will think that the first {} is skipped and the entire The statement is considered to be a +{} statement, which is equivalent to the Number({}) function call operation that forces the numerical value to be calculated, which is equivalent to the Number("[object Object]") operation, and the final result is NaN. This problem can be avoided by adding parentheses ({}) + {}.

  • Empty object + empty array
console.log({} + []);        //"[object Object]"

Empty objects and empty arrays are added together. The left and right operands first call valueOf() to return the object array itself, and then call toString() to return the original data type, that is, object string [object Object] and "". Perform a connection operation to obtain characters. string[object Object]

Directly console.log will get the same value, but enter directly in the browser console:

> {} + []
0

> [] + {}
"[object Object]"

{} + [] is equivalent to the +[] statement, which is equivalent to the Number([]) operation that forces a numeric value. It is equivalent to the Number("") operation, and the final result is the number 0.

  • Date object
console.log(1 + (new Date()));       //"1Tue Aug 14 2018 21:18:24 GMT+0800 (中国标准时间)"

The preferred type of Date object is String. First call toString() to get the string and perform string concatenation operations.

To get the valueOf return value in a Date object, you need to use the unary plus sign (+) to force it to a numeric type, such as the following code:

console.log(+new Date());
1534298171747
  • Symbols type The
    Symbols data type newly added in ES6 is neither a general value nor an object. It does not have an internal automatic transformation design, so it cannot be directly used for addition operations at all, and an error will be reported when used.

  • +[]/+{}

console.log(+[]);     // 0
console.log(+{});     // NaN
console.log(+null);     //0
console.log(+true);     //1
console.log(+undefined);     //NaN

In the unary plus sign operation, the only operand is equivalent to the Number([]) operation that forces a numeric value.

Guess you like

Origin blog.csdn.net/qq_29510269/article/details/106375786